ES6学习之路(二) 变量的解构赋值

时间:2022-12-26 12:27:26

1.数组解构赋值

什么事解构赋值:从数组或对象中提取值,对变量进行赋值;
总结:
数组解构赋值
1.等号两边的模式相同,左边的变量会被赋值上相对应的值;
2.等号右侧的值多于左侧变量时,变量只解构自身对应的值;
3.等号的右边不是数组或者不是可遍历的结构,就会报错;
4.解构赋值允许变量设置默认值,默认值可以是表达式;
5.默认值可以应用其他变量,但是这个变量必须提前声明了;
6.等号右侧的值必须 === Undefined ,默认值才会生效,否则就被右边赋值;

let [a,b,c]=[1,2,3];
console.log(a,b,c);//1,2,3
let a=1;
let b=2;
let c=3;
console.log(a,b,c);//123

上面两个代码的结果都是一样的,显然第一个代码更简洁
本质上来说,只要等号两边的模式相同,左边的变量会被赋值上相对应的值。

    let [foo,[[bar],baz]] = [1,[[2],3]];
console.log(foo,bar,baz);//1,2,3

let [ , ,third] = ['foo','bar','baz'];
console.log(third);//baz 等号左侧与右侧相互对应

let [x,,y]=[1,2,3];
console.log(x,y);//1 3 原理同上

let [head,...tail] = [1,2,3,4];
console.log(head,tail);//1,[2,3,4]
//...tail这个变量前面的三个点叫做 Rest parameters(剩余参数),就是说从它对应的值开始后面所有的参数都被整合到一个数组里面与 arguments有点类似,所以后面输出的是1,[Rest parameters]

let [x1,y1,...z] = ['a'];//a,undefined,[];
//与上面情况相同,x的值是a,因为等号右边没有对应y变量的值,等于声明变量没有赋值,所以返回Undefined,后面的z就是Rest参数,即使没有被赋值也会返回一个空的数组.

不完全解构
当等号右侧的值多于左侧变量时,变量只解构自身对应的值,其余的不管,这种情况被称为不完全解构

let [x1,y1]=[1,2,3];
console.log(x1,y1);//1,2

如果等号的右边不是数组或者不是可遍历的结构,那么就会报错,或者说具有Iterator接口可以实现遍历的参数,都可以进行数组形式的解构赋值比如 Set 结构 & Generator 函数

    //都会报错
let [foo]=1;
let [foo]=false;
let [foo]=NaN;
let [foo]=undefined;
let [foo]=null;
let [foo]={};

默认值
解构赋值允许变量设置默认值

    let [foo=true] =[]
console.log(foo);//true

//如果等号右边的值不是严格等于Undefined,那么默认值不会生效
let [x,y='b']=['a'];//x=a;y=b
let [x1,y1='b']=['a',undefined];//x=a;y=b
//undefined===undefined,默认值生效

let [x2,y2='b']=['a',null];//x=a;y=null
//undefined===null,不严格等于,默认值不生效
console.log(undefined===null);//false

默认值可以是表达式

    //如果默认值是表达式 ,默认值是惰性的,只有在用到的时候才会求值;
function f(){
console.log('aaa');
}

let [x=f()]=[1];
console.log(x);//1
//上面代码也就说当 等号右边没有值的时候,或者值为Undefined时,才会取到f函数
    //默认值可以应用其他变量,但是这个变量必须提前声明了;
let [x=1,b=x]=[];
console.log(x,b);//1,1

//也就相当于let声明的规则,必须在声明后使用变量
let [y=c,c=1]=[];
console.log(y,c);//c is not defined

2.对象的解构赋值

对象与数组的解构赋值的不同点在于,数组需要按照次序拍列,对象只需要属性名与变量名相同即可了;
总结:
1.对象解构的内部处理机制==={匹配名:变量名}={匹配名:变量的值},没用特定变量名,那么{匹配名===变量名};
2.与数组解构赋值相同,等号左右两边的模式必须相同;
3.let与const不可重复声明;
4.修改变量的值,需要用圆括号括起来,否则浏览器会把一对花括号理解为一个块级作用域;
5.解构赋值允许变量设置默认值,默认值可以是表达式;
6.默认值可以应用其他变量,但是这个变量必须提前声明了;
7.对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
8.可以对数组进行对象属性的解构;

    let {foo,bar}={bar:'bbb',foo:'aaa'};
console.log(foo,bar);//aaa,bbb

let{baz}={bar:'bbb',foo:'aaa'};
console.log(baz);//undefined
//上方代码由于等号右侧没有与之想对应的属性名,返回Undefined

对象解构赋值的内部机制
先找到同名的属性,然后再给后者的变量赋值,前者与后者名字可以不同

    let {foo:foo,bar:bar}={foo:'aaa',bar:'bbb'};
console.log(foo);
    //变量名与属性名不一致,需要写成下面的方式,
var {foo:baz}={foo:'aaa',bar:'bbb'};
console.log(baz);//aaa
// console.log(foo);//foo is not defined

let obj = {first:'hello',last:'world'};
let {first:f,last:l}=obj;
console.log(f,l);//hello,world

在使用let和const声明变量的时候,由于它们自身的特性,不可以重复声明,否则就报错

    let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

let baz;
let {bar: baz} = {bar: 1}; // SyntaxError: Duplicate declaration "baz"
    //如果要修改变量的值,需要用圆括号括起来,否则浏览器会把一对花括号理解为一个块级作用域;
let foo;
({foo}={foo:1});

let bar;
({bar:baz}={bar:1});
//对象解构赋值,嵌套赋值;按照对象的结构来生成变量
let obj = {
p:[
'hello',
{y:'world'}

]
};
let {p:[x,{y}]}=obj;
console.log(x,y);//hello world;
    let obj = {};
let arr = [];

({foo:obj.prop,bar:arr[0]}={foo:123,bar:true});
console.log(obj.prop,arr);
//对象也可以指定默认值
let {x=3}={};
console.log(x);
let {x:y=3}={};
console.log(y);
//对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
let {log,sin,cos}=Math;
console.log(sin);
//可以对数组进行对象属性的解构
let arr=[1,2,3];
let {0:first,[arr.length-1]:last}=arr;
console.log(first,last);

字符串解构赋值


const [a,b,c,d,e] ='hello';
console.log(a,b,c,d,e);//h,e,l,l,o

//字符串length属性解构赋值
let {length:len}='hello';
console.log(len);

数值和布尔值解构赋值


//如果等号右边的值不是对象或者数组,那么就现将其转化成对象,
//由于undefined和null无法转换成对象,所以对他们进行解构赋值会报错
let {toString:s}=123;
console.log(s===Number.prototype.toString)//true

let {toString:t}=true;
console.log(t===Boolean.prototype.toString)//true

函数参数默认值,与数组对象默认值的方法相同,也可以使用默认值

    function add([x, y]){
return x + y;
}

add([1, 2]); // 3

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]