ES6解构赋值

数组的解构赋值

ES6中允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这称为解构赋值,在ES5中为变量赋值,只能直接指定值

首先,有几个简单的例子

1)左边和右边“模式匹配”,完全解构,按照对应的位置,为变量赋值

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

//略微复杂一点的嵌套,但是也是模式匹配的
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo, bar, baz);  //1 2 3

babel编译后的代码

"use strict";

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

console.log(a, b, c); //1 2 3

发现“模式匹配”的情况下,编译出的代码就是单个定义的

2)左边和右边“非模式匹配”,部分解构

let [,,third] = [3, 5, 7];
console.log(third);  //7

//和扩展运算符一同使用
let [head, ...tail] = [1, 2, 3, 4];
console.log(head, tail);// 1  [2, 3, 4]

let [x, y, ...z] = [1];
console.log(x, y, z);// 1 undefined []

解构不成功,变量的就等于undefined,因为有扩展运算符,所以z的值为空数组

bable后的代码

第一段的话,就是定义了个数组,赋值为右边的值,然后,给指定变量赋予指定的值

"use strict";

var _ref = [3, 5, 7];
var third = _ref[2];

console.log(third); //7

第二段的话,是含有扩展运算符的,就是单独定义

"use strict";

var head = 1;
var tail = [2, 3, 4];

console.log(head, tail);

第三段的话,可以看作是前面两个的综合

"use strict";

var _ref = [1];
var x = _ref[0];
var y = _ref[1];

var z = _ref.slice(2);

console.log(x, y, z); // 1 undefined []

需要注意的地方:如果等号右边的不是数组(不是可遍历的结构)就会报错,当然只要转为带有Iterator接口的对象就好了

let [re] = 1;
let [x, y, z] = new Set([1, 2, 4]);

3)默认值的情况

let [x = 1] = [];
console.log(x);  // 1

当默认值和右边同时有值的话,那么取的是等号右边的[]中的值

let [y, z = 2] = [3, 4];
console.log(z); //4

let [r = 99] = [null];
console.log(r);  //null

当为undefined的时候取得就是默认值

let [r = 99] = [undefined];
console.log(r);

对象的解构赋值

1)简单的情况

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

对象的属性是没有次序的,变量必须和属性同名,才能取得到正确的值,babel后的代码如下

'use strict';

var _bar$foo = { bar: 'aaa', foo: 'bbb' };
var foo = _bar$foo.foo;
var bar = _bar$foo.bar;

console.log(foo, bar); // bbb  aaa

当没有同名属性的时候,就等于undefined

let {brr} = {bar : 999};
console.log(brr); // undefined

对象赋值的机制是,先找到同名属性,然后再赋给对应的变量,真正被赋值的是后者,而不是前者

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

前面的代码可以看做是下面的简写方式

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

2)多层嵌套的方式

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

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

这段代码,建议通过自己的理解,写出等号左边的部分,如果写出来了,就说明对于对象和数组的结构赋值有了比较清晰的认识,数组的左边定义变量的形式是[],对象的左边定义变量的形式是{}

const node = {
    loc: {
        start : {
            line: 1,
            column: 5
        }
    }
};

let {loc, loc: {start : {line, column}}} = node;
console.log(loc, line, column);// { start: { line: 1, column: 5 } }  1  5

3)默认值的情况,和数组的是类似的,这里就不在赘述

4)已经声明的变量用于解构赋值的情况

//会出现错误,js引擎会将{x}理解为一个代码块,从而发生了语法错误
let x;
{x} = {x: 1};

正确的写法,需要加一对括号

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

babel后的代码

"use strict";

var x = undefined;
var _x = { x: 1 };
x = _x.x;
_x;

5)几个特殊的用法

将现有对象的方法,赋值给某个变量

let {sin, cos, tan} = Math;

数组也可以进行对象属性的解构

let arr = [1, 2, 3];
let {0: first, [arr.length-1]: last} = arr;
console.log(first, last);  // 1 3

字符串的解构赋值

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

函数参数的结构赋值

1)不含默认值

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

var res = add([1, 2]);
console.log(res);// 3

babel后的结果

"use strict";

var _slicedToArray = (function () {
    function sliceIterator(arr, i) {
        var _arr = [];
        var _n = true;
        var _d = false;
        var _e = undefined;
        try {
            for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _
                arr.push(_s.value);
                if (i && _arr.length === i)
                    break;
            }
        } catch (err) {
            _d = true; _e = err;
        } finally {
            try {
                if (!_n && _i["return"])
                    _i["return"]();
            } finally {
                if (_d)
                    throw _e;
            }
         }
         return _arr;
    }

    return function (arr, i) {
        if (Array.isArray(arr)) {
            return arr;
        } else if (Symbol.iterator in Object(arr)) {
            return sliceIterator(arr, i);
        } else {
            throw new TypeError("Invalid attempt to destructure non-iterable instance");
        } };
    })();

function add(_ref) {
    var _ref2 = _slicedToArray(_ref, 2);

    var x = _ref2[0];
    var y = _ref2[1];

    return x + y;
}

var res = add([1, 2]);
console.log(res);

大概看了一下_slicedToArray这个函数,感觉它的作用就是产生真的数组

[[1, 2], [3, 4]].map(([a, b]) => {
    console.log(a + b);
});// 3, 7

2)包含默认值的情况

为变量x和y指定默认值,函数的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值,解构失败的情况下,x和y等于默认值

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

var res = move({x: 3, y: 4});
console.log(res); //[3, 4]
console.log(move());// [0, 0]
console.log(move({}));// [0, 0]

为函数参数指定默认值

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

var res = move({x: 3, y: 4});
console.log(res); //[ 3, 4 ]
console.log(move());// [ 1, 2 ]
console.log(move({}));// [ undefined, undefined ]

undefined可以触发函数的默认值

[1, undefined, 3].map((x= 88) => console.log(x));  // 1 88 3

用途

1)交换两个变量的值

let x = 1;
let y = 2;

[x, y] = [y, x];
console.log(x, y); // 2 1

2)从函数中返回多个值

//返回数组
function example() {
    return [3, 4, 5];
}

let [a, b, c] = example();
console.log(a, b, c);
//返回对象
function test() {
    return {
        foo : 1,
        bar : 2
    };
}

let {foo, bar} = test();
console.log(foo, bar);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值