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

12 篇文章 0 订阅

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

三、变量的解构赋值

1、数组的解构赋值

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

基本用法

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

let [A,,[[B]],...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 循环遍历。
·
补充:
Iterator
遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作。
作用:

  • 为各种数据结构,提供一个统一的、简便的访问接口
  • 使得数据结构的成员能够按某种次序排列
  • ES6创造了一种新的遍历命令 for … of 循环,Iterator 接口主要供 for … of 使用

    ES6中有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set 和 Map 结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值