最近笔者在系统研究ES6,对于阮一峰ES6中的函数参数解构赋值的示例起初有些不理解。
原文中举了两个例子:1、为函数参数变量指定默认值;2、为函数参数指定默认值。
这两者是有区别的,代码如下:
// 1、为函数参数变量x、y指定默认值
function move({x = 0, y = 0} = {}){
return [x, y];
}
move({x:3, y:8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
// 2、为函数参数指定默认值{0, 0}
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
不理解笔者上面归纳的两个点,没有关系,下面慢慢分析。
示例1中,不少人会疑惑,为什么要像 {x = 0, y = 0} = {} 这么写,根据之前学的对象的解构赋值,难道不可以直接写 {x = 0, y = 0} 吗,答案是可以,但是这么写不够完善,我们可以对比看输出结果。
// 3、函数参数采用{x = 0, y = 0},而非{x = 0, y = 0} = {}
function move({x = 0, y = 0}){
return [x, y];
}
move({x:3, y:8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // Uncaught TypeError: Cannot read property 'x' of undefined
可以看到,与 {x = 0, y = 0} = {} 不同是:{x = 0, y = 0} 写法执行move()会报错,所以前者是考虑了这种情况,而避免报错。
而为什么会报错呢,这里有个重要知识点:当进行解构赋值时,等式右边的对应模式(对象属性、数组成员)严格等于undefined时,默认值生效。
当在执行move()时:
示例1实际上发生了:
let [ obj = {}] = arguments; // arguments此时可看作[]
let {x = 0, y = 0} = obj;
上面的arguments在《JavaScript高级程序设计》的 5.5.4 函数内部属性 章节中有解释
在函数内部,有两个特殊对象:arguments和this。其中,arguments是一个类数组对象,包含着传入函数中的所有参数。
执行move()时,arguments可以看作空数组[ ]。
类似的,示例3实际上发生了:
let [{x = 0, y = 0}] = [];
事实上,这个赋值表达式是会报错的
这正是之前示例3中,执行move()的报错。
分析到此,相信大家应该已经了解了为什么要函数参数中要采用 {x = 0, y = 0} = {},此时再去分析示例2{x, y} = {x:0, y:0}相信已经很容易了。