Skip to content

JavaScript 函数高级

函数对象的属性

属性name:函数名

属性length:返回函数参数个数

属性arguments:一个对应于 传递给函数的参数 的 类数组(array-like)对象

array-like 意味着它不是一个数组类型,而是一个对象类型:

  • 但是它却拥有数组的一些特性,比如说 length,比如可以通过 index 索引来访问;
  • 但是它却没有数组的一些方法,比如 filter、map 等;

注意

箭头函数没有arguments

函数的剩余参数

ES6 中引用了 rest parameter,可以将不定数量的参数放入到一个数组中:

如果最后一个参数是 ... 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;

js
function foo(m, n, ...args) {}

那么剩余参数和arguments有什么区别呢?

  • 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;
  • arguments 对象不是一个真正的数组,而 rest 参数是一个真正的数组,可以进行数组的所有操作;
  • arguments 是早期的 ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而 rest 参数是 ES6 中提供并且希望以此来替代 arguments 的;

纯函数

函数式编程中有一个非常重要的概念叫纯函数,JavaScript 符合函数式编程的范式,所以也有纯函数的概念;

  • react 开发中纯函数是被多次提及的;
  • 比如 react 中组件就被要求像是一个纯函数(为什么是像,因为还有 class 组件),redux 中有一个 reducer 的概念,也是要求必须是一个纯函数;
  • 所以掌握纯函数对于理解很多框架的设计是非常有帮助的;

纯函数的维基百科定义

  • 在程序设计中,若一个函数符合以下条件,那么这个函数被称为纯函数:
  • 此函数在相同的输入值时,需产生相同的输出
  • 函数的输出和输入值以外的其他隐藏信息或状态无关,也和由 I/O 设备产生的外部输出无关。
  • 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等。

简单总结:

  • 确定的输入,一定会产生确定的输出;
  • 函数在执行过程中,不能产生副作用;

柯里化

柯里化(Currying)是把接收多个参数的函数,变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数,而且返回结果的新函数的技术;

柯里化是一种函数的转换,将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)

柯里化的优势

  1. 函数职责单一
  • 在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
  • 那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果;
  1. 函数参数复用

通过闭包,复用上层函数的参数

js
const makeAdder = (num) => (count) => num + count

自动柯里化函数:将普通函数,转换成柯里化函数

js
function autoCurring(fn) {
  function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args)
    } else {
      return function (...args2) {
        return curried.apply(this, args.concat(args2))
      }
    }
  }
  return curried
}

严格模式

JavaScript 历史的局限性

  • 长久以来,JavaScript 不断向前发展且并未带来任何兼容性问题;
  • 新的特性被加入,旧的功能也没有改变,这么做有利于兼容旧代码;
  • 但缺点是 JavaScript 创造者的任何错误或不完善的决定也将永远被保留在 JavaScript 语言中;

在 ECMAScript5 标准中,JavaScript 提出了严格模式的概念(Strict Mode):

  • 严格模式很好理解,是一种具有限制性的 JavaScript 模式,从而使代码隐式的脱离了 ”懒散(sloppy)模式“;
  • 支持严格模式的浏览器在检测到代码中有严格模式时,会以更加严格的方式对代码进行检测和执行

严格模式对正常的 JavaScript 语义进行了一些限制:

  • 严格模式通过 抛出错误 来消除一些原有的 静默(silent)错误;
  • 严格模式让 JS 引擎在执行代码时可以进行更多的优化(不需要对一些特殊的语法进行处理);
  • 严格模式禁用了在 ECMAScript 未来版本中可能会定义的一些语法;

如何开启严格模式?

  1. 在 js 文件首行填入
js
// "use strict"
  1. 在某个函数中开启
js
function foo() {
  'use strict'
}

严格模式限制

  1. 无法意外的创建全局变量
  2. 严格模式会使引起静默失败(silently fail,注:不报错也没有任何效果)的赋值操作抛出异常
  3. 严格模式下试图删除不可删除的属性
  4. 严格模式不允许函数参数有相同的名称
  5. 不允许 0 的八进制语法
  6. 在严格模式下,不允许使用 with
  7. 在严格模式下,eval 不再为上层引用变量
  8. 严格模式下,this 绑定不会默认转成对象