小谈ES6解构赋值

解构赋值

解构赋值指的是按照一定规则,直接从数组和对象中提取值,对变量进行赋值。

数组的解构赋值

基本用法

解构匹配

只要左右两边的模式相同,左边的变量就会被赋予对应的值。如果解构不成功,则返回undefined。

let [d,b,c] = [1,2,3]; // => d=1;b=2;c=3
let [[f]] = [[1]];  // =>f=1
let [e,...tail] = [1,2,3,4]; // =>e=1;tail = [2,3,4]

这里let [a, b, c]表示定义了用于数组解构的三个全局变量a, b, c。解构采取贪婪匹配原则,尽量解构更多的数据,并且即使模式不是完全匹配,也能部分解构成功。

但要注意下面的陷阱:

let [a, [b], c] = [1, [2, 3], 4]; // b=>2
// 如果想让b的值解构后为[2,3],需要写成
let [a,[...b],c] = [1, [2, 3], 4];
// 或者最简单的
let [a, b, c] = [1,[2,3],4]

上面rest(…)运算符必须出现在末尾,否则会报错。

右值的要求

在进行对数组的解构赋值时,等号右边必须是可遍历的解构,比如说数组,Set集合甚至Generator对象。否则会报错。

字符串在解构时会被转化成一个类似数组的对象,因此可以用于数组的解构赋值

let [a, b, c] = 'hello' // => a=h; b=e; c=l

默认值

默认值何时生效

可以指定解构赋值时的默认值,当右值数组成员严格等于undefined时,默认值才会生效。

let [a = 'hello'] = []; //a='hello'
let [a = 'hello'] = [null]; //a=null
惰性

如果默认值是表达式,它的求值方式是惰性的,只有需要使用默认值的时候,才进行计算

let foo = () => {
    console.log('fooing');
    return 'foo'
};
let [b = foo()] = [];  // 会执行foo函数
let [b = foo()] = ['bar']; // 不会执行foo函数

对象的解构赋值

基本用法

let {c, d} = {c:'c,e:'e'',d:'d'};
console.log(c);
console.log(d);

与数组解构的一个不同之处在于对象解构把[]换成了{}, let {c, d} 定义了两个全局变量:c,d。

此外,对象解构赋值是和对象属性的定义顺序无关的,只要名称能够匹配,即左边的变量名与右边的属性名相同,就可以取得正确的值。为了告诉你们这点,我特意把e安排到了d前面。

我不希望把属性名当做变量名

很多时候我们不希望我们的局部变量名和属性名完全相同,那么可以采取下面的办法:

let {foo:baz} = {foo:'foo',bar:'bar'}; // => baz=foo

格式是:

{属性名:变量名... ...}={属性名:值...}

也就是说只需要在属性名后面加”:希望的变量名”就可以了。

那么,你肯定能够想到,我们开始时写的这种形式:

let {c, d} = {c:'c,e:'e'',d:'d'};

其实是下面形式的简写,因为它们的属性名和变量名是相同的。真正被赋值的其实是后者:

let {c:c, d:d} = {c:'c,e:'e'',d:'d'};

使用()告诉引擎我在用解构赋值呢

如果一个已经声明的变量进行解构赋值,大概会像下面这样:

let foo;
{foo} = {foo:'foo'} // 报错

这是因为大括号写在了首行,JS引擎会把它当成一个代码块,解决办法很简单,加上()就可以了:

({foo} = {foo:'foo'})

注意,除了这里以及函数表达式调用的时候可能要用到(),我们使用解构赋值的时候尽量不要使用(),因为它几乎没有用处,还容易导致各种错误出现

对象当然也可以设置默认值了

前面提到过的

let {foo:foo,bar:baz} = {foo:'foo',bar:'bar'}

在进行解构赋值时,实际上是先通过左边的foo,bar属性名去到右边匹配属性,然后把匹配到的属性的值赋给左边的:后的变量名。那么你就不难想到,对象解构可以像下面这样设置默认值:

let {foo='bbb',bar:baz='aaa'} = {foo:'foo',bar:'bar'}

上面的代码foo代表属性名和变量名相同的情况,baz代表不同的情况。

右值的要求

使用对象解构赋值时,右值可以是简单数据类型布尔、字串或者数字。解构时,会先将其转化为对象,再进行解构。

右值不得是不能转成对象的null或undefined,否则会报错。

嵌套解构

解构赋值本身非常灵活,所以可以进行匹配模式的嵌套:

let {arr:[x,{prop}]} = {arr:[1,{prop:2}]};
console.log(x); // =>1
console.log(prop); // =>2
console.log(arr); // 报错,未定义

上面代码中的arr是匹配模式的一部分,所以不会被赋值。

应用

这里举两个比较常见但不提又不容易想到的应用

交换两个变量的值

[foo,bar] = [bar,foo];

定义函数的参数

var foo = ([x, y])=>x+y;
foo([1,2]) // =>3

或者以对象的形式,这样可以优化以配置对象形式编写函数参数方式的代码

var bar = ({x, y, z=5}) => x-y+z
bar({x:1, y:2}) // => 4

但需要注意的是,不要把解构赋值默认参数与ES6函数本身默认参数的特性相混淆。

基本上解构赋值需要注意的点都在这里了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值