arguments、默认参数、剩余参数和箭头函数有什么差异?
先理解原理和示例,再练习完整口述与追问。
回答要点
普通函数有 arguments,它是类数组。严格模式下它和具名参数不再互相同步。默认值从左到右计算,可以引用前面的参数,后面的参数还在暂时性死区。剩余参数是真正的数组,不包含已具名的参数。箭头函数没有自己的 this、arguments、new.target,也不能 new。
原理拆解
非严格模式的普通函数里,修改具名参数会反映到 arguments,反过来也一样,这是早期的别名行为。严格模式取消了别名:改参数不影响 arguments,改 arguments[i] 也不影响参数。ES Module 和 class 体本身就是严格模式。
默认值在调用时、且该参数是 undefined 时才计算,传入 null 不会触发默认值。计算按参数顺序进行,默认表达式里可以读前面已经初始化的参数,不能读后面尚未初始化的参数。function.length 只统计第一个默认值或剩余参数之前的参数个数。
剩余参数收集“多出来的实参”,function f(a, ...rest) 里 rest 不含 a,并且是数组,能直接 map。它和 arguments 同时存在时,arguments 仍包含全部实参。箭头函数不建立自己的 arguments 和 this,写在箭头函数里的这两个名字解析到外层;它也没有 prototype,不能作为构造函数。
示例与推演
function loose(a) { a = 2; return arguments[0] }
function strict(a) { 'use strict'; a = 2; return arguments[0] }
console.log(loose(1), strict(1)) // 2 1
function pair(a = 1, b = a) { return [a, b] }
console.log(pair()) // [1, 1]
function bad(a = b, b = 1) { return [a, b] }
bad() // ReferenceError,计算 a 时 b 还在暂时性死区
const outer = function () {
return () => arguments.length
}
console.log(outer(1, 2)()) // 2,箭头函数看到的是 outer 的 arguments
易错点
默认参数不会把 null 换成默认值。不要在箭头函数里找“自己的 arguments”。剩余参数已经是数组,不必再 Array.from;arguments 才需要转换。
参考回答可直接练习口述
普通函数有类数组 arguments。非严格模式下它和具名参数互相同步,严格模式下不再同步。默认值只在传入 undefined 时从左到右计算,可以读前面的参数,读后面的会落入暂时性死区;null 不会触发默认值。剩余参数是真正的数组,只包含多出来的实参。箭头函数没有自己的 this、arguments 和 prototype,不能 new,这两个名字都会到外层去找。