有关函数传参的结构赋值的理解

结构赋值是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;

这样分析下来是不是就容易理解多了,以上是查阅资料后的个人拙见,如有不妥处,请指正,谢谢!

原文地址:https://www.cnblogs.com/cmyoung/p/9111948.html