博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6变量的解构赋值
阅读量:6855 次
发布时间:2019-06-26

本文共 5257 字,大约阅读时间需要 17 分钟。

1. 数组的解构赋值

在ES5中,为变量赋值必须采用直接赋值的形式

var foo = 'abc'var bar = 123复制代码

利用ES6的解构赋值,可以简化为

let [foo, bar] = ['abc', 123]复制代码

上面的代码表示,声明foo和bar两个变量,并且按照两边数组中的顺序一一初始化值,实际上解构赋值的写法属于一种“模式匹配”,这种“模式匹配”还可以用于更复杂的数据解构中。

let [foo, [[bar, baz], qux]] = ['147', [['258', '369'], 'abc']]foo // '147'    bar // '258'baz // '369'    qux // 'abc'let [, , foo] = ['147', '258', '369']foo // '369'const [foo, bar, ..., qux ] = ['a', 'b', 'c', 'd', 'e'];foo // 'a'bar // 'b'qux // 'e'let [foo, [bar, ...baz]] = ['a', ['b', 'c', 'd', 'e']]foo // 'a'bar // 'b'baz // ['c', 'd', 'e']let [x, y, ...z] = ['a'];x // "a"y // undefinedz // []复制代码

如果赋值方无法满足被赋值方的结构, 则部分变量解构不成功,解构不成功的变量等于undefined, 以下情况baz解构不成功, 值为undefined。赋值方的值,有且只有undefined无法使解构赋值失败/默认值生效

var [baz] = [];var [qux, baz] = [1];复制代码

如果赋值方能满足被赋值方的结构, 而且还有多余,则能匹配的部分就解构成功

let [foo, [bar], qux] = [1, [2, 3], 4]foo // 1bar // 2qux // 4复制代码

如果赋值方是不可遍历的结构, 则解构会报错

// 报错let [qux] = 1;let [qux] = false;let [qux] = undefined;复制代码

对于Set结构,也可以使用数组的解构赋值。

let [x, y, z] = new Set(["a", "b", "c"]);x // "a"复制代码

事实上,只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。 下面的代码中fibs是一个Generator函数,原生带有iterator接口, 解构赋值依次从iterator 接口取值

function* fibs() {  var a = 0;  var b = 1;  while (true) {    yield a;    [a, b] = [b, a + b];  }}var [first, second, third, fourth, fifth, sixth] = fibs();sixth // 5复制代码

解构赋值允许指定默认值

[x, y = 'b'] = ['a']; // x='a', y='b'[x, y = 'b'] = ['a', null]; // x='a', y=null[x, y = 'b'] = ['a', undefined]; // x='a', y='b'复制代码

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。下面代码中,因为x能取到值,所以函数f根本不会执行。

function f() {  console.log('aaa');}let [x = f()] = [1];复制代码

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

let [x = 1, y = x] = [2];    // x=2; y=2let [x = 1, y = x] = [1, 2]; // x=1; y=2let [x = y, y = 1] = [];     // ReferenceError复制代码

2. 对象的解构赋值

简单的对象解构赋值:

const { foo, bar } = { foo: "a", bar: "b" };foo // "a"bar // "b"复制代码

数组的解构赋值是依据按数组元素的顺序依次解构的,不同的是,对象的解构赋值对属性的顺序没有要求,而是需要属性名相对应才能成功解构赋值。

const { bar, foo } = { foo: "aaa", bar: "bbb" };foo // "aaa"bar // "bbb"const { qux } = { foo: "aaa", bar: "bbb" };qux // undefined复制代码

上面的第二个例子,在赋值方找不到属性名qux,被赋值方的取不到值,为undefined

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

let obj = { first: 'hello', last: 'world' };let { first: f, last: l } = obj;f // 'hello'l // 'world'复制代码

回顾对象解构赋值的第一个例子,其写法实际是以下写法的简写。

const {foo: foo, bar: bar} = {foo: "a", bar: "b"}复制代码

下面的代码中,先用let声明变量,再在解构赋值中参与赋值,注意行首的圆括号是必须的,因为以大括号起首的语句会被执行器认为是匿名代码块,而不是解构赋值,所以需要用圆括号表示其意义

let foo;({foo} = {foo: 1}); // 成功let baz;{bar: baz} = {bar: 1}; // 报错复制代码

解构赋值用于对象和数组嵌套的解构, 注意k和p是属性名,只有a和b才是被赋值的变量

const foo = {    k: [        '123',        {            p: '456'        }    ]}const {k: [a, {p: b}]} = foo;a // '123'b  // '456'k // error: k is undefinedp // error: p is undefined复制代码

把被赋值方的值解构赋值到对象/数组中

const o = {}, a = [];({name: o.name, age: a[0]} = {name: 'Miku', age: 10})o // {name: 'Miku'}a // [10]复制代码

对象的解构赋值也可以指定默认值

var {x = 3} = {};x // 3var {x, y = 5} = {x: 1};x // 1y // 5复制代码

和数组的解构赋值一样,被赋值方有且只有undefined可以使解构赋值失败/默认值生效

var {x = 3} = {x: undefined};x // 3var {x = 3} = {x: null};x // null复制代码

对象的解构赋值,可以很方便地将现有对象的值(包括简单类型,引用类型,函数等),赋值到某个变量。

const {promise1, promise2} = fn()Promise.all(promise1, promise2).then(...)复制代码

3. 函数参数的解构赋值

函数的参数也可以使用解构赋值

function add([x, y]){  return x + y;}add([1, 2]); // 3复制代码

函数参数的解构也可以使用默认值。

function move({x = 0, y = 0} = {}) {  return [x, y];}move({x: 3, y: 8}); // [3, 8]move({x: 3}); // [3, 0]move({}); // [0, 0]move(); // [0, 0]复制代码

和对象的解构赋值一样,函数参数的赋值方有且只有undefined能使解构失败/默认值生效

[1, undefined, 3].map((x = 'yes') => x);// [ 1, 'yes', 3 ]复制代码

4. 其他类型的解构赋值

解构赋值的规则是,只要赋值方的值不是对象,就先将其转为对象。

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';a // "h"b // "e"c // "l"d // "l"e // "o"复制代码

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

let {length : len} = 'hello';len // 5复制代码

数值和布尔值解构赋值时,会先转为对象。

let {toString: s} = 123;s === Number.prototype.toString // truelet {toString: s} = true;s === Boolean.prototype.toString // true复制代码

由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

let { prop: x } = undefined; // TypeErrorlet { prop: y } = null; // TypeError复制代码

5. 应用场景

交换变量的值,不再需要创建中间值

[foo, bar] = [bar, foo];复制代码

分别获取函数返回的多个值

function fn () {    return {foo: '123', bar: '234'}}const {foo, bar} = fn()复制代码

函数接收参数时直接解构

function fn ({foo, bar, qux}) {    return `${foo} ${bar} ${qux}!`}const param = {    foo: 'Welcome',    bar: 'to',    qux: 'javascript'}console.log(fn(param))//Welcome to javascript!复制代码

提取json中的值作为变量

const person = {    name: 'Miku',    age: 1,    birth: '1996-2-18'}let {name, age, birth} = person;console.log(name, age, birth)//Miku 1 1996-2-18复制代码

遍历ES6 Map解构, 如果只想把key赋值给变量, 可以写成[key], 如果指向把value赋值给变量,则写[, value]

const areas = new Map()areas.set('浙江省', '杭州市')areas.set('广东省', '广州市')for (let [key, value] of areas) {  console.log(`${key}-${value}`);}//浙江省-杭州市//广东省-广州市复制代码

node module.exports/require函数和ES6 export/import

//node module.exports/requireconst person = {name: 'Miku', age: 1}const student = {grade: 3, class: 2}module.exports = {person, student}const {person} = require('......')console.log(person)//{name: 'Miku', age: 1}//ES6 export/importexport const fnCollect = {    fn1 () {        return 'this is fn1'    },    fn2 () {        return 'this is fn2'    }}//importimport {fn1} from '......'console.log(fn1())//this is fn1复制代码

转载于:https://juejin.im/post/5b0e0410518825158d0e734f

你可能感兴趣的文章
网络高手修身
查看>>
JavaWeb综合案例-键盘模拟
查看>>
Android Day03-SQLite数据库操作及ListView详解
查看>>
HTTP请求GET/POST查看工具
查看>>
php实现 坐标移动
查看>>
前端之HTML
查看>>
The Cats' Feeding Spots
查看>>
Python 进阶_OOP 面向对象编程_self 的实例绑定
查看>>
jquery内核学习(5)--对象的遍历
查看>>
在Android迷你广告上添加浮动的关闭按钮
查看>>
2dcontext
查看>>
企业级大数据处理方案-01
查看>>
计算机的组成与操作系统
查看>>
包冲突getJspApplicationContext
查看>>
Webrtc入门——基于阿里云ubuntu 最新webrtc Android平台编译详细说明
查看>>
iOS 图文混排 链接 可点击
查看>>
poj 1240
查看>>
UI设计时要注意的几个方面
查看>>
SVN 更新失败
查看>>
kmp循环节
查看>>