ES6学习笔记2 变量的解构赋值

基本用法

ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值

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

如果对应变量解构不成功,则该变量的值将会为undefined

let [x,y] = [1];
x   //1
y   //undefined

如果=的右边不是可迭代的结构,就会报错。事实上,只要某种数据结构具有Iterator接口,就可以采用数组形式的解构赋值,例如Set结构,Generator函数

let [foo] = 1;     //报错
let [foo] = true;  //报错
let [foo] = null;  //报错
let [foo] = undefined;  //报错
let [x,y,z] = new Set(['a','b','c']);
x     //'a'
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

默认值

解构赋值允许指定默认值,若对应的变量解构后值为undefined,则将采用默认值,,否则默认值不生效

let [x=1] = [];
x     //1

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

如果默认值是一个表达式,则这个表达式是惰性求值的,即只有将其作为默认值赋值时才会求值

function f(){
    return 2;
}

let [x = f()] = [1];

上述代码中,因为x能取到值,因此函数f不会执行
默认值可以引用其他变量,但该变量必须已经声明

let [x=1, y=x] = [2]    //x=2,y=2
let [x=y, y=1] = []     //报错,因为y未声明就被先使用

对象的解构赋值

对象的解构与数组有一个重要不同,对象的属性没有次序,变量必须与属性名同名才能取到正确的值

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

如果变量名与属性名不一致,必须写成如下格式

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

实际上,对象的解构赋值是下面形式的简写

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

这表示对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者

let {foo:baz} = {foo:'aaa', bar:'bbb'};
baz   //'aaa'
foo   //报错,foo未定义

与数组一样,解构也可以用于嵌套结构的对象

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

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

对象的解构也可以指定默认值,默认值生效的条件与数组类似

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

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

如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,将会报错,原因在于此时将对undefined取子属性

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

如果要将一个已经声明的变量,用于解构赋值,应该小心

let x;
{x} = {x:1};  //报错

上述javascript会将{x}理解为一个代码块,只有不将大括号写在行首,才能避免此问题

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

常见应用
获取Math对象的方法

let {log, sin, cos} = Math;

获取数组项

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

字符串的解构赋值

字符串被转换为一个类似于数组的对象

const [a,b,c] = 'xyz';
a    //'x'
b    //'y'
c    //'z'
let {length:len} = 'xyz';
len  //3

数值和布尔值的解构赋值

如果等号右边是数值和布尔值,则会先转化为对象,再赋值

let {toString:s} = 123;
s  //'123'

let {toString:s} = true;
s  //'true'

此处数值和布尔值包装对象都有toString属性,因此他们都能取到值

函数参数的解构赋值

参数传入那一刻,自动被解构赋值

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

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

可以使用默认值

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

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

圆括号问题

以下情况不能使用圆括号:

  • 变量声明语句
let [(a)] = [1];  //报错
  • 函数参数
function f([(z)]){
    return z;
}  //报错
  • 赋值语句的模式
([a]) = [5];   //报错

({p:a}) = {p:1};   //报错

圆括号只能使用在赋值语句的非模式部分

[(b)] = [3];    //正确

({p:(d)}] = {});   //正确

上述第一行语句,模式是取数组第一个成员,与圆括号无关。第二个语句,模式是p,与圆括号无关。

用途

从函数返回多个值

function example(){
    return [1,2,3];
}
let [a,b,c] = example();

函数参数的定义

function f([x,y,z]){ ... }
f([1,2,3]);

提取JSON数据

let jsonData = {
    id:42,
    status:'ok',
    data:[1,2,3]
}

let {id,status,data} = jsonData;

函数默认参数值、遍历Map结构、输入模块指定方法等

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/80802202