您的位置:首页 > Web前端 > JavaScript

js -- ES6(三)-- 变量的解构赋值(根据阮一峰ES6标准入门整理 更新中。。。)

2018-01-12 15:28 756 查看
6>目前正在学习ES6,学到哪更新到哪里,都是基本的知识,复杂的目前还不会,涉及的代码都是亲自运行过的,若发现错误请指正。

三、变量的解构赋值

1、数组的解构赋值

解构:按照一定模式,从数组和对象中提取值,对变量进行赋值

基本用法

从数组中提取值,按照位置的对应关系对变量赋值,只要等号两边的模式相同,左边的变量就会被赋予对应的值

① 解构成功

let [A,,[],...Z]=[1,2,[[3],4],5,6];
console.log(A);//1
console.log(B);//3
console.log(Z);//[5,6]


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

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


③ 不完全解构 ,等号左边的模式只匹配等号右边数组的一部分

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


④ 解构失败,等号的右边是不可遍历的结构,会报错

let [foo] =1;           //undefined is not a function
let [foo] =false;       //undefined is not a function
let [foo] =NaN;         //undefined is not a function
let [foo] =undefined;   //Cannot read property 'Symbol(Symbol.iterator)' of undefined
let [foo] =null;        //Cannot read property 'Symbol(Symbol.iterator)' of null
let [foo] ={};          //undefined is not a function


默认值

解构赋值允许指定默认值

[x,y='b']=['a'];
console.log(x);//'a'
console.log(y);//'b'


ES6使用严格相等运算符(===)判断一个位置是否有值,所以,如果一个数组成员不严格等于undefined,默认值是不会生效的

var [x=1]=[undefined];
console.log(x);//1,严格等于undefined,默认值生效

var [x=1]=[null];
console.log(x);//null,不严格等于undefined,默认值不生效


如果默认值是一个表达式,那么这个表达式是惰性求值的,只有在用到的时候才会求值

例如下面的例子,因为x能取到值,所以函数 f 根本不会执行

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


等价于:

function f(){
console.log('aaa');
}
const a = [1];
let x;
if(a[0]==undefined){
x=f();
}else{
x=a[0];
}
console.log(x);//1


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

let [x=1,y=x] = [];//1,1
let [x=1,y=x] = [2];//2,2
let [x=1,y=x] = [1,2];//1,2
let [x=y,y=1] = [];//y is not defined, x 用到默认值 y 时,y 还没有声明


2、对象的解构赋值

对象的解构与数组有一个重要的不同,数组的元素是按照次序排列的,变量的取值由它的位置决定。对象的属性没有次序,变量只要与属性同名,就能取到正确的值。

① 变量与属性同名

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

var {hh} = {foo:'aaa',bar:'bbb'};
console.log(hh);//undefined,变量没有对应的同名属性,导致取不到值,等于undefined


② 变量名与属性名不一致

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


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

③ 重复声明

对于 let 和const 而言,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错

let hh;
let {foo:hh} = {foo:1};
console.log(hh);//Identifier 'hh' has already been declared标识符“hh”已经声明


如果没有第二个 let 命令,就不会报错

let hh;
({foo:hh} = {foo:1});
console.log(hh);//1


④ 嵌套赋值,模式不会被复制

var {loc:{start:{line}}} = node;
console.log(loc);//log is not defined
console.log(start);//start is not defined
console.log(line);


这里只有 line 是变量,loc 和 start 都是模式,不会被赋值

⑤ 对象解构指定默认值,默认值生效的条件是对象的属性值严格等于undefined。

var {x=3} = {x:undefined};
console.log(x);//3

var {x=3} = {x:null};
console.log(x);//null

var {foo} = {bar:'fff'};
console.log(foo);//undefined
var {foo:{bar}} = {fff:'fff'}//Cannot match against 'undefined' or 'null'.


⑥ 解构赋值已经声明的变量

var x;
{x}={x:1}
console.log(x);//Unexpected token =


报错原因是,js引擎会将{x}理解成一个代码块,从而发生语法错误。

正确的写法:不将大括号写在行首,避免js将其解释为代码块

var x;
({x}={x:1});
console.log(x);//1


3、字符串的解构赋值

字符串解构赋值时,字符串被转换成了一个类似数组的对象。

const [a,b,c,,d] = 'hello';
console.log(a);//a
console.log(d);//o


类似数组的对象都有length属性,因此还可以对这个属性解构赋值。

let {length} = 'hello';
console.log(length);


4、数值和布尔值的解构赋值

① 等号右边是数值或布尔值,先转化为对象再赋值

let {toString:s}=123;
console.log(s===Number.prototype.toString)//true

let {toString:s}=true;
console.log(s===Boolean.prototype.toString);//true

ps:不是很懂什么意思


② undefined 和 null 无法转为对象,解构赋值会报错

let {prop:x} = undefined;
//Cannot match against 'undefined' or 'null'.
let {prop:y} = null;
//Cannot match against 'undefined' or 'null'.


5、函数参数的解构赋值

function move({x=0,y=0}={}){
return [x,y];
}
console.log(move({x: 3, y: 8}));//[3,8]
console.log(move({x: 3}));//[3,0]
console.log(move({}));//[0,0]
console.log(move());//[0,0]
函数 move 的参数是一个对象,通过对这个对象进行解构,得到变量 x 和 y 的值。如果解构失败,则 x 和 y 等于默认值。


function move({x,y}={x:0,y:0}){
return [x,y];
}
console.log(move({x: 3, y: 8}));//[3,8]
console.log(move({x: 3}));//[3,undefined]
console.log(move({}));//[undefined,undefined]
console.log(move());//[0,0]
函数 move 的参数指定默认值,而不是为变量 x 和 y 指定默认值


6、圆括号问题

不能使用圆括号的情况

① 变量声明语句中,模式不能带有圆括号

// Unexpected token (
var [(a)] = [1];
var {x:(c)} = {};
var {o:({p:p})} = {o:{p:2}};


② 函数参数中,模式不能带有圆括号,函数参数也属于变量声明

// Unexpected token (
function f([(z)]) {
return z;
}
console.log(f(2));


③ 不能将整个模式或嵌套模式中的一层放在圆括号中。

// Unexpected token (
//整个模式
({p:a}) = {p:42};
([a]) = [5];
//嵌套模式
[({p:a}),{x,c}] = [{},{}];


可以使用圆括号的情况

① 赋值语句的非模式部分可以使用圆括号

[(b)] = [3];
console.log(b);//3
({p:(d)} = {});
console.log(d);//undefined
[(parseInt.prop)] = [3];
console.log(parseInt.prop);//3


7、解构赋值的用途

(1)交换变量的值

[x,y] = [x,y];


(2)从函数返回多个数值

函数只能返回一个值,如果要返回多个值,只能将其放在数组或对象中返回

//返回一个数组
function example() {
return [1,2,3];
}
var [a,b,c] = example();
console.log([a, b, c]);//[1,2,3]


//返回一个对象
function example() {
return {
foo:1,
bar:2
};
}
var {foo,bar} = example();
console.log({foo,bar});//{foo:1,bar:2}


(3)函数参数的定义

(4)提取JSON数据

(5)函数参数的默认值

(6)遍历 Map 结构

部署了Iterator 接口的对象,都可以用 for … of 循环遍历。

·

[b]补充:


Iterator

遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作。

作用:

为各种数据结构,提供一个统一的、简便的访问接口

使得数据结构的成员能够按某种次序排列

ES6创造了一种新的遍历命令 for … of 循环,Iterator 接口主要供 for … of 使用

ES6中有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set 和 Map 结构
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: