变量的解构赋值

一、为什么要使用解构赋值?

在学习ES6新的特性解构赋值之前,我们先来看看为什么要使用解构,以前如果我们需要获取对象或者数组里面的数据,并且把它们存入数组,需要写很多代码。如下

const person = {
  name: 'MengXiangJi',
  age: 18,
  sex: '男'
}
let age = person.age
let name = person.name
let sex = person.sex

我们想在一个对象中获取相应的数据,需要写很多重复的代码,基于此,es6为我们推出了解构赋值这个特性。我们可以更简单的获取对象或者数组中的数据。

二、什么是解构赋值

解构赋值语法是一个Javascript表达式,这使得可以将数据从数组或对象提取到不同的变量中(这段话是mdn中关于解构赋值的定义,注意这里的定义,可以看出解构主要用在数组和对象上)。
还是上面这个需求,如果我们使用解构赋值的方法,那么书写方式如下

const person = {
  name: 'MengXiangJi',
  age: 18,
  sex: '男'
}
let { name, age, sex } = person 

对比之前的写法,是不是简洁了很多?

三、 对象的解构赋值

  • 基本用法

对象的解构赋值,变量必须与属性同名,才能取到正确的值。

 let a = {
        name:'meng',
        age:18
    }
    let {name,age} = a
    console.log(name,age) // meng 18

可以起一个别名,还是上面的代码

let a = {
        name:'meng',
        age:18
    }
    let {name:b,age} = a
    console.log(b,age) // meng 18

上面这段代码也可以拿到name的值

  • 默认值

先来看段代码

let a = {
        age:18
    }
    let {name ,age} = a
    console.log(name,age) // undefined 18

这个时候,对象a中没有name属性,解构的时候会取不到值,所以name是undefined,这时候我们可以给name赋值一个默认值,当name严格等于undefined时,会使用默认值

    let a = {
        age:18
    }
    let {name = 111,age} = a
    console.log(name,age) // 111 18

注意,下面这种是错误的写法

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

四、数组的结构赋值

  • 基本用法
let [a, b, c] = [1, 2, 3];
console.log(a,b,c)  // 1 2 3

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。

let [c] = [];
console.log(c)  //  undefined

如果解构不成功,变量的值就等于undefined

let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

如果等号的右边不是数组,那么将会报错。

  • 占位
let [, , c] = [1, 2, 3];
console.log(c)  //  3

如果我们只想拿到3的话,可以用逗号进行占位

  • 不完全解构
let [x, y] = [1, 2, 3];
console.log(x,y)  // 1 2

即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。

  • 默认值
let [foo = true] = [];
foo // true

这里的默认值使用方法和对象的一样

五、字符串的解构赋值

  • 基本用法
const [a, b, c, d] = 'meng';
console.log(a,b,c,d) // m  e  n  g

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

六、函数参数的解构赋

  • 基本用法
function a([x, y]){
  return x + y;
}

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

函数a的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和y。对于函数内部的代码来说,它们能感受到的参数就是x和y。

  • 默认值
function a([x , y = 5]){
  return x + y;
}

a([2]); // 7

七、圆括号的问题

解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。

由此带来的问题是,如果模式中出现圆括号怎么处理。ES6 的规则是,只要有可能导致解构的歧义,就不得使用圆括号。

但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置圆括号。

  • 不能使用圆括号的情况

变量声明语句

// 全部报错
let [(a)] = [1];

let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};

let { o: ({ p: p }) } = { o: { p: 2 } };

函数参数

// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }

赋值语句的模式

// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
  • 可以使用圆括号的情况

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。

posted @ 2019-02-10 20:25  我会放电啪啪  阅读(201)  评论(0编辑  收藏  举报