变量的解构赋值

2017-10-25  本文已影响16人  Kris_lee

es6-2 (变量的解构赋值)

本文以及之后的文章都是参考
阮一峰ES6入门
,记录下作为笔记。

数组的解构赋值

对象的解构赋值

字符串的解构赋值

数值和布尔值的结构赋值

函数参数的结构赋值

圆括号问题

用途

1 .数组的解构赋值

let a = 1;
let b = 2;
let c = 3;

ES6允许写成下面这样

let [a, b, c] = [1, 2, 3];

eg:

let[x,y,...z] = ['a']
x // "a"
y // "undefined"
z // []

如果解构不成功,变量的值就等于undefined.
事实上,子要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值

function* fibs() {
  let a = 0;
  let b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5

上面代码中,fibs是一个Generator函数,原生具有Iterator接口,解构赋值回一次从这个接口获取值。

默认值
let[x=1] = [undefined];
x //1
let [x = 1] = [null]
x //null

上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined
如果默认值是一个表达式,那么这个表达式是惰性求值,即只有在用到的时候,才会求值。

function f(){
console.log('aaa')
}
let [x=f()] = [1]

上面代码中,因为x能取到值,所以函数f根本不会执行,上面的代码其实等价于下面的代码。

let x;
if([1][0] === undefined){
x = f()
}else{
    x = [1][0] 
}

默认值可以引用结构赋值的其他变量,但该变量必须已经声明。

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError

上面最后一个表达式之所以回报错,是因为x用到默认值y时,y还没有声明

对象的结构赋值

let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

对象的黑狗与数组有一个重要的不同,数组的元素是俺次序排列的,变量的取值由它的未知决定而对象的属性没有次序,变量必须与属性同名,才能渠道正确的值

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined    

也就是说,对象的结构赋值的内部机智,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者
与数组一样,结构也可以用于嵌套结构的对象。

let obj = {
    p:[
    'hello',
    {y:'world'}
    ]
}

let {p:[x,{y}]} = obj;
console.log(x+'  '+y);
console.log(obj.p[0]);
console.log(obj.p[1].y);

对象的解构也可以指定默认值。

var {x = 3} = {};
x // 3

var {x, y = 5} = {x: 1};
x // 1
y // 5

var {x: y = 3} = {};
y // 3

var {x: y = 3} = {x: 5};
y // 5

var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong"

如果要将一个已经声明的变量用于解构赋值,必须非常小心

函数的参数的解构赋值
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]

注意下面的写法会得到不一样的结果

function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

上面代码是为函数move的桉树指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。

undefined就会触发函数参数的默认值。

let arr = [1,undefined,4];
arr.map((x = 'yes')=>{
    console.log(x);
})

圆括号问题。

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

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

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

用途。

let x = 1;
let y = 2;
[x, y] = [y, x];
    // 返回一个数组
    
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    // 返回一个对象
    
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();
上一篇下一篇

猜你喜欢

热点阅读