参数扩展与收集
在给函数传参时,有时候可能不需要传入一个数组,而是要分别传入数组的元素。如果不使用扩展操作符,想把定义在这个函数这面的数组拆分,那么就得求助于apply方法
在ES6中,可以通过扩展操作符极为简洁地实现这种操作,对可迭代对象应用扩展操作符,并将其作为一个参数传入,可以将可迭代对象拆分,并将迭代返回的每个值单独传入
因为数组长度已知,所以在使用扩展操作符传参的时候,并不妨碍在其前后再传其他的值,包括使用扩展操作符传其他参数
在构思函数定义时,可以使用扩展操作符把不同长度的独立参数组合成一个数组,这有点类似arguments对象的构造机制,只不过收集参数的结果会得到一个Array实例
收集参数的前面如果还有命名参数,则只会收集其余的参数;如果没有则会得到空数组。因为收集参数的结果可变,所以只能把它作为最后一个参数
箭头函数虽然不支持arguments对象,但支持收集参数的定义方式,因此也可以实现与使用arguments一样的逻辑
使用收集参数不影响arguments对象,它仍然反映调用时传给函数的参数
函数声明与函数表达式
JS引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。而函数表达式必须等到代码执行到它那一行,才会在执行上下文中生成函数定义
函数声明会在任何代码执行之前先被读取并添加到执行上下文。这个过程叫做函数声明提升。在执行代码时,JS引擎会先执行一遍扫描,把发现的函数声明提升到源代码树的顶部,因此即使函数定义出现在调用它们的代码之后,引擎也会把函数声明提升到顶部,如果把函数声明改为等价表达式,那么执行时会报错
函数作为值
不仅可以把函数作为参数传给另一个函数,而且还可以在一个函数中返回另一个函数
如果是访问函数而不是调用函数,那就必须不带括号
从一个函数中返回另一个函数也是可以的,而且非常有用
函数内部
arguments:是一个类数组对象,包含调用函数时传入的所有参数,这个对象只有以function关键字定义函数时才会有,该对象其中还有一个callee属性,指向arguments对象所在函数的指针,用作递归中可以让函数逻辑与函数名解耦
this
在标准函数中,this引用的是把函数当成方法调用的上下文对象,这时候通常称其为this值
箭头函数中this引用的是定义箭头函数的上下文
caller:这个属性引用的是调用当前函数的函数,如果是在全局作用域中调用的则为null
严格模式下访问arguments.callee会报错,arguments.caller也是
new.target:ES中的函数始终可以作为构造函数实例化一个新对象,也可以作为普通函数被调用。如果是普通调用,则new.target的值是undefined,如果是new关键字调用的,则new.target将引用被调用的构造函数
函数属性与方法
length属性保存函数定义的命名参数的个数
prototype是保存引用类型所有实例方法的地方,由所有实例共享
apply()和call()方法都会以指定的this值来调用函数,即会设置调用函数时函数体内this对象的值。
apply()方法接收两个参数:函数内this的值和一个参数数组。第二个参数可以是Array实例,也可以是arguments对象
在严格模式下,调用函数时,如果没有指定上下文对象,则this值不会指向window。除非使用apply或call把函数指定给一个对象,否则this的值会变成undefined
call()方法与apply()方法一样,只是传参的形式不同,第一个参数也是this值,而剩下的要传给被调用函数的参数则是逐个传递的。
使用call()和apply()的好处是可以将任意对象设置为任意函数的作用域,这样对象可以不用关心方法
bind()方法会创建一个新的函数实例,其this值会被绑定到传给bind()的对象
继承的toLocaleString()和toString()方法时钟返回函数的代码,返回代码的格式因浏览器而异。valueOf()返回函数本身