函数名的提升
JavaScript 引擎将函数名视同变量名,所以采用function
命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。所以,下面的代码不会报错。
1 | f(); |
表面上,上面代码好像在声明之前就调用了函数f
。但是实际上,由于“变量提升”,函数f
被提升到了代码头部,也就是在调用之前已经声明了。所以,上面的代码等同于下面的形式
1 | var f = function () {} |
而且不是只提升了 f
这个变量,是整个函数内容(即 function f()
)都被提升上去了
但是,如果采用赋值语句定义函数,JavaScript 就会报错。
1 | f(); |
上面的代码等同于下面的形式。
1 | var f; |
上面代码第二行,调用f
的时候,f
只是被声明了,还没有被赋值,等于undefined
,所以会报错。因此,如果同时采用function
命令和赋值语句声明同一个函数,最后总是采用赋值语句的定义。
1 | var f = function () { |
同时采用function
命令和赋值语句声明同一个函数,执行该函数时,如果涉及函数名提升的,总是采用 function
定义的函数(也可以说是, function
声明的函数名的提升的优先级要比赋值语句声明的优先级要高)
1 | f() |
1 | f() |
参考:函数名的提升
类数组对象
定义(没有官方定义):只包含使用从零开始,且自然递增的整数做键名,并且定义了length表示元素个数的对象,我们就认为它是类数组对象
1 | var arrayLike = { |
类数组对象转为数组的方法:
-
使用 Array 原型链上的 slice 方法
1
2var array = Array.prototype.slice.call(arrayLike);
var array = [].slice.call(arrayLike); -
使用 for 循环
1
2
3
4var len = arrayLike.length, array = new Array(len)
for(var i = 0; i < len; i++) {
array.push(arrayLike[i])
} -
使用对象的扩展运算符
1
var array = [...arrayLike]
-
使用 Array 的 from 方法
1
var array = Array.from(arrayLike)
arguments对象
arguments 是一个对应于传递给函数的参数的类数组对象。
arguments
对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments
对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。
正常模式
在正常模式下,arguments
对象可以在运行时修改,并且 arguments
对象与函数参数具有绑定的关系。
1 | function foo(a) { |
上面代码中,arguments[0] 与 a 是绑定了一起的,更改了其中一个,另一个也会更改。
但是,如果在函数运行时给 arguments 对象添加新的元素 (arguments 的 length 属性的值不会改变),则此新添加的元素与函数参数是没有绑定关系的
(注意:arguments 对象是跟函数的实参绑定的)
1 | function test(a, b, c) { |
严格模式
严格模式下,arguments
对象与函数参数不具有绑定关系。也就是说,修改arguments
对象不会影响到实际的函数参数。
1 | function foo(a) { |
剩余参数、默认参数和解构赋值参数
当非严格模式中的函数有包含剩余参数、默认参数和解构赋值,那么arguments
对象中的值不会跟踪参数的值(反之亦然)。相反, arguments
反映了调用时提供的参数:
1 | // 剩余参数 |
1 | function foo(a = 55) { |