有关函数传参的结构赋值的理解
结构赋值是es6 中增加的非常实用的新功能,能提高我们的编码效率。但是,有时候在函数参数中用时,常常会出错,例如下面
eg1:
function foo({x = 0, y = 0} = {}) { return [x, y]; } console.log(foo({x: 6, y: 8}));// [6, 8] console.log(foo({x: 6}));// [6, 0] console.log(foo({}));// [0, 0] console.log(foo());// [0, 0]
如果我们把上述例子改成下面
eg2:
function foo({x, y} = { x: 0, y: 0 }) { return [x, y]; } console.log(foo({x: 6, y: 8})); // [6, 8] console.log(foo({x: 6})); // [6, undefined] console.log(foo({})); // [undefined, undefined] console.log(foo()); // [0, 0]
结果是不是超出你的想象!
查阅资料后才发现,其实是这样的:
eg1 是给变量x,y指定默认值,eg2 是给函数的参数指定默认值。
首先,简单说明一下基本的对象解构赋值操作中解构赋值默认值的使用:
let { x = 0, y = 0 } = { x: 6, y: 9 }; console.log(x);//6 console.log(y);//9
在简单的解构赋值操作中,等号左边的对象是变量组成的,我在这里称它左变量(为了后文方便理解,姑且这样定义)即:x,y,等号右边的部分是真正的值,这里称它为右真值;而左变量中x,y等号右边的部分分别为变量x和变量y的默认值。它们之间的关系是:当右侧x,y没有指定值的时候(也就是x===undefined和y===undefined的时候),变量的默认值会生效,而当x,y指定了值的时候,变量的默认值不会生效。那么什么是衡量x,y是否===undefined的标准呢?可以是以下几种情况:
1.右侧没有对应的属性 let { x = 0, y = 0 } = { y: 9 };//这种情况下属性x就是undefined,那么此时变量的默认值生效,所以输出:x为0,y为9 2.右侧属性值就是undefined let { x = 0, y = 0 } = { x:undefined,y: 9 };
值得特别说明的是:这里判断默认值是否生效的是右真值是否===undefined,而不是==undefined,两者有什么区别呢?在js中undefined==null是成立的,而undefined===null是不成立的。关于这一点可以通过在浏览器中输入下面的代码验证:
console.log(undefined===null);//false console.log(undefined==null);//true
所以,这里得到这样的结论:
let { x = 0, y = 0 } = { x:null,y: 9 }; console.log(x);//null console.log(y);//9
也就是说,undefined===null是false,所以默认值不能生效,所以最终结果是null。
现在,再说明一下函数参数默认值,如下:
function fun(a = 0){
...
} fun();//这里函数调用时,没有传实参,所以默认值0生效; fun(6);//这里传递了实参,所以实参是6;
所以,函数参数默认值生效的标准是函数调用时没有传递实参;
那么我们再来分析一下上面的两个例子:
eg1:
function foo({x = 0, y = 0} = {}) { return [x, y]; } console.log(foo({x: 6, y: 8}));// [6, 8]
//说明:传递了实参,所以函数默认值{}不生效,对实参{x: 6, y: 8}解构赋值,对应的属性都有值,所以解构赋值的默认值不生效,所以x = 6,y = 8; console.log(foo({x: 6}));// [6, 0] //说明:传递了实参,所以函数默认值{}不生效,对实参{x: 3}解构赋值,对应的属性x有值,y没有值,所以解构赋值的默认值y生效,x不生效,所以x = 6,y = 0; console.log(foo({}));// [0, 0] //说明:传递了实参{},所以函数默认值{}不生效,对实参{}解构赋值,对应的属性都没有值,所以解构赋值的默认值生效,所以x = 0,y = 0; console.log(foo());// [0, 0] //说明:没有传递实参,所以函数默认值{}生效,对实参{}解构赋值,对应的属性都没有值,所以解构赋值的默认值生效,所以x = 0,y = 0;
eg2:
function foo({x, y} = { x: 0, y: 0 }) {
return [x, y];
} console.log(foo({x: 6, y: 8})); // [6, 8]
//说明:传递了实参,所以函数默认值{x: 0, y: 0}不生效,对实参{x: 6, y: 8}解构赋值,对应的属性都有值,所以解构赋值的默认值不生效,所以x = 6,y = 8;
console.log(foo({x: 6})); // [6, undefined] //说明:传递了实参,所以函数默认值{x: 0, y: 0}不生效,对实参{x: 6}解构赋值,对应的属性x有值,y没有值,所以x=6,因为本例没有解构赋值的默认值,所以y就是undefined;
console.log(foo({})); // [undefined, undefined] //说明:传递了实参{},所以函数默认值{x: 0, y: 0}不生效,对实参{}解构赋值,对应的属性没有值,所以x,y就是undefined;
console.log(foo()); // [0, 0] //说明:没有传递实参,所以函数默认值{x: 0, y: 0}生效,对实参{x: 0, y: 0}解构赋值,对应的属性有值,所以x,y就是0;
这样分析下来是不是就容易理解多了,以上是查阅资料后的个人拙见,如有不妥处,请指正,谢谢!