ES6学习——变量的解构赋值

参考文档:https://es6.ruanyifeng.com/

解构:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构

  1. 本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值
  2. 解构不成功,左边变量没有在等号右侧找到对应的数据,变量的值就等于undefined
  3. 不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成
  4. 如果等号的右边不是数组(或者严格地说,不是可遍历的结构)将会报错。Set 结构,也可以使用数组的解构赋值。只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值

例子如下:

尤其注意:数组解构时...的写法相当于取子集

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

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

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [a] = 1;
//TypeError: 1 is not iterable
let [x, y, z] = new Set([1,2,3,4]);
console.log(x,y,z);
//输出
1 2 3

4、解构赋值允许指定默认值。

let [a=true] = [];
console.log(a);
//输出
true
let [x, y = 'b'] = ['a', undefined]; 
console.log(x,y);
//输出
a b
let [z=2] = [1]; 
console.log(z);
//输出
1

注意:当匹配到的值是undefined,默认值会生效;只有当一个数组成员严格等于undefined,默认值才会生效。

 

5、默认值是表达式惰性求值,只有用到才会求值

function f() {
  return 2;
}
let [x = f()] = [3];
console.log(x);
//输出 3

x能取到值3,所以函数f根本不会执行

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

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: y is not defined

二、对象的解构赋值

对象的解构与数组有一个重要的不同。

数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值

没有对应的同名属性导致取不到值,最后等于undefined

let {a,b} = { b: 'b',a: 'a' };
a //'a'
b //'b'
let {a} = {b:1}
a // undefined

1、对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量

const { log } = console;
log(1) 
//输出 1

注意,这里看上去和常见的解构没有一一对应,但是console也是对象

2、如果变量名与属性名不一致,必须写成下面这样

let { a: x } = { a:1 };
// x=1

3、内部机制

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

let { a: x } = { a:1 };
console.log(a);
//ReferenceError: a is not defined

4、解构也可以用于嵌套结构的对象,类似数组

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]

注意:第一个p匹配obj内部的所有值,第2个p是模式

5、如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错

let {a:{b}} = {b: 2};
//TypeError: Cannot destructure property `b` of 'undefined' or 'null'

6、对象的解构赋值可以取到继承的属性

const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);
const { foo } = obj1;
console.log(foo) 
// "bar"

7、对象的解构也可以指定默认值并且默认值生效的条件是,对象的属性值严格等于undefined

 

8、注意:

(1)如果要将一个已经声明的变量用于解构赋值

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: Unexpected token =

报错原因:JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题

// 正确的写法
let x;
({x} = {x: 1});

(2)数组本质是特殊的对象,因此可以对数组进行对象属性的解构。注意模式是下标

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

数值和布尔值的解构赋值

解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象

let {toString: s} = 123;
s === Number.prototype.toString // true

函数参数的解构赋值

圆括号问题

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

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

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

变量解构赋值用途

1、交换变量值

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

2、从函数返回多个值

js函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便

3、函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。

4、提取 JSON 数据

5、函数参数的默认值

6、遍历 Map 结构

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

Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world

只想获取键名,或者只想获取键值,如下

// 获取键名
for (let [key] of map) {
  // ...
}

// 获取键值
for (let [,value] of map) {
  // ...
}

7、输入模块的指定方法

加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰

const { SourceMapConsumer, SourceNode } = require("source-map");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值