解析JavaScript的ES6版本中的解构赋值

什么是解构赋值?

解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性值赋给一系列变量。这个语法非常简洁,而且比传统的属性访问更加清晰。

在不使用解构赋值的情况下,访问数组的前三项:

var first = someArray[0];
var second = someArray[1];
var third = someArray[2];

var first = someArray[0];
var second = someArray[1];
var third = someArray[2];

使用解构赋值后,相应的代码变得更简洁和可读:

var [first, second, third] = someArray;

var [first, second, third] = someArray;

SpiderMonkey(Firefox 的 JavaScript 引擎)已经支持解构赋值的大部分特性,但还不完全。
数组和可迭代对象的解构赋值

上面我们已经看到了数组解构赋值的例子,该语法的一般形式是:

[ variable1, variable2, ..., variableN ] = array;

[ variable1, variable2, ..., variableN ] = array;

这将把数组中对应的项依次赋给 variable1 到 variableN,如果同时需要声明变量,可以在解构表达式前面添加 var,let 或 const 关键字。

var [ variable1, variable2, ..., variableN ] = array;
let [ variable1, variable2, ..., variableN ] = array;
const [ variable1, variable2, ..., variableN ] = array;

var [ variable1, variable2, ..., variableN ] = array;
let [ variable1, variable2, ..., variableN ] = array;
const [ variable1, variable2, ..., variableN ] = array;

事实上,你还可以嵌套任意的深度:

var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3

var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3

此外,还可以跳过数组中的某些项:

var [,,third] = ["foo", "bar", "baz"];
console.log(third);
// "baz"

var [,,third] = ["foo", "bar", "baz"];
console.log(third);
// "baz"

你还可以用一个 Rest 表达式来捕获数组中的剩余项:

var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]

var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]

如果数组越界或访问数组中不存在的项,将得到和通过数组索引访问一样的值:undefined。

console.log([][0]);
// undefined

var [missing] = [];
console.log(missing);
// undefined

console.log([][0]);
// undefined

var [missing] = [];
console.log(missing);
// undefined

注意,数组解构赋值的方式也同样适用于可遍历的对象:

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();
console.log(sixth);
// 5

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();
console.log(sixth);
// 5

对象的解构赋值

对象的解构赋值允许你将变量绑定到对象不同的属性值。指定被绑定的属性名,后面紧跟要绑定的变量:

var robotA = { name: "Bender" };
var robotB = { name: "Flexo" };

var { name: nameA } = robotA;
var { name: nameB } = robotB;

console.log(nameA);
// "Bender"
console.log(nameB);
// "Flexo"

var robotA = { name: "Bender" };
var robotB = { name: "Flexo" };

var { name: nameA } = robotA;
var { name: nameB } = robotB;

console.log(nameA);
// "Bender"
console.log(nameB);
// "Flexo"

当绑定的属性名和接收属性值的变量名一样时,还有一个语法糖:

var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo);
// "lorem"
console.log(bar);
// "ipsum"

var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo);
// "lorem"
console.log(bar);
// "ipsum"

与数组一样,也可以嵌套:

var complicatedObj = {
 arrayProp: [
  "Zapp",
  { second: "Brannigan" }
 ]
};

var { arrayProp: [first, { second }] } = complicatedObj;

console.log(first);
// "Zapp"
console.log(second);
// "Brannigan"

var complicatedObj = {
 arrayProp: [
  "Zapp",
  { second: "Brannigan" }
 ]
};

var { arrayProp: [first, { second }] } = complicatedObj;

console.log(first);
// "Zapp"
console.log(second);
// "Brannigan"

解构一个不存在的属性时,将得到 undefined:

var { missing } = {};
console.log(missing);
// undefined

var { missing } = {};
console.log(missing);
// undefined

使用对象的解构赋值时还有一个潜在的陷阱,在解构赋值时没有声明变量(没有 var、let或 const 关键字):

{ blowUp } = { blowUp: 10 };
// Syntax error

{ blowUp } = { blowUp: 10 };
// Syntax error

这是因为 JavaScript 语法告诉引擎任何以 { 开始的语句都是语句块(例如,{console} 就是一个合法的语句块),解决方法是将整个语句用一对括号包裹:

({ safe } = {});
// No errors

({ safe } = {});
// No errors

其他情况

当你尝试解构 null 或 undefined,你将得到类型错误:

var {blowUp} = null;
// TypeError: null has no properties

var {blowUp} = null;
// TypeError: null has no properties

不过,你可以对其他基本类型(Boolean、String 和 Number)进行解构,将得到 undefined:

var {wtf} = NaN;
console.log(wtf);
// undefined

var {wtf} = NaN;
console.log(wtf);
// undefined

结果也许会让你感到意外,但深究一下,其实原因很简单。在进行对象解构赋值时,被解构的对象将被强制转换为 Object,除 null 和 undefined 外,其它类型都可以被强制转换为对象。进行数组的结构赋值时,要求被解构的对象有一个遍历器。
默认值

可以为不存在的属性指定一个默认值:

var [missing = true] = [];
console.log(missing);
// true

var { message: msg = "Something went wrong" } = {};
console.log(msg);
// "Something went wrong"

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

var [missing = true] = [];
console.log(missing);
// true

var { message: msg = "Something went wrong" } = {};
console.log(msg);
// "Something went wrong"

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

实际应用
函数参数

作为开发人员,我们经常把一个包含多个属性的对象作为函数的参数,来实现更灵活的 API,而不是让 API 的使用者记住一些特定顺序的参数。我们可以使用对象的解构赋值,来避免每次使用参数时的属性访问:

function removeBreakpoint({ url, line, column }) {
 // ...
}

function removeBreakpoint({ url, line, column }) {
 // ...
}

配置对象

完善上面的例子,我们可以为要被解构的对象属性提供默认值,这在对那些作为配置参数的对象非常实用,因为许多配置项都有一个合理的默认值。例如,jQuery 的 ajax 方法的第二个参数为一个配置对象,我们可以这样实现:

jQuery.ajax = function (url, {
 async = true,
 beforeSend = noop,
 cache = true,
 complete = noop,
 crossDomain = false,
 global = true,
 // ... more config
}) {
 // ... do stuff
};

jQuery.ajax = function (url, {
 async = true,
 beforeSend = noop,
 cache = true,
 complete = noop,
 crossDomain = false,
 global = true,
 // ... more config
}) {
 // ... do stuff
};

这避免了类似这样的重复代码:var foo = config.foo || theDefaultFoo;。
与迭代器一起使用

当遍历 Map 对象时,我们可以使用解构赋值来遍历 [key, value]:

var map = new Map();
map.set(window, "the global");
map.set(document, "the document");

for (var [key, value] of map) {
 console.log(key + " is " + value);
}
// "[object Window] is the global"
// "[object HTMLDocument] is the document"

var map = new Map();
map.set(window, "the global");
map.set(document, "the document");

for (var [key, value] of map) {
 console.log(key + " is " + value);
}
// "[object Window] is the global"
// "[object HTMLDocument] is the document"

只遍历键:

for (var [key] of map) {
 // ...
}

for (var [key] of map) {
 // ...
}

只遍历值:
for (var [,value] of map) {
 // ...
}

for (var [,value] of map) {
 // ...
}

返回多个值

返回一个数组,通过解构赋值提取到返回值:

function returnMultipleValues() {
 return [1, 2];
}
var [foo, bar] = returnMultipleValues();

function returnMultipleValues() {
 return [1, 2];
}
var [foo, bar] = returnMultipleValues();

或者,返回一个键值对的对象:

function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var { foo, bar } = returnMultipleValues();

function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var { foo, bar } = returnMultipleValues();

这两者都比使用中间变量好:

function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var temp = returnMultipleValues();
var foo = temp.foo;
var bar = temp.bar;

function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var temp = returnMultipleValues();
var foo = temp.foo;
var bar = temp.bar;

采用延续式:

function returnMultipleValues(k) {
 k(1, 2);
}
returnMultipleValues((foo, bar) => ...);

function returnMultipleValues(k) {
 k(1, 2);
}
returnMultipleValues((foo, bar) => ...);

导入 CommonJS 模块的指定部分

还没使用过 ES6 的模块吧,那至少使用过 CommonJS 吧。当导入一个 CommonJS 模块 X 时,模块提供的方法也许多余你实际使用的。使用解构赋值,你可以明确指定你需要使用模块的哪些部分:

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

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

如果你使用 ES6 的模块机制,你可以看到 import 声明时有一个类似的语法。
结论

我们看到,解构赋值在很多场景下都很实用。在 Mozilla,我们已经有很多经验。Lars Hansen 在 10 年前就向 Opera 引入了解构赋值,Brendan Eich 在稍微晚点也给 Firefox 添加了支持,最早出现在 Firefox 2 中。因此,解构赋值已经渗透到我们每天对 JS 的使用中,悄悄地使我们的代码更简短、整洁。

(0)

相关推荐

  • ES6新特性之解构、参数、模块和记号用法示例

    本文实例讲述了ES6新特性之解构.参数.模块和记号用法.分享给大家供大家参考,具体如下: 一.解构 解构提供了一个方便的地从对象或数组中提取数据的方法,请看下面的例子: //ES6 let [x,y]=[1,2];//x=1,y=2 //ES5 var arr=[1,2]; var x=arr[0]; var y=arr[1]; 使用这个语法,可以一次性给多个变量赋值.一个很好的附加用处是可以很简单的交换变量值: let x=1,y=2; [x,y]=[y,x];x=2 y=1 解构也可以用于对

  • 深入浅出讲解ES6的解构

    什么是解构? 解构与构造数据截然相反. 例如,它不是构造一个新的对象或数组,而是逐个拆分现有的对象或数组,来提取你所需要的数据. ES6使用了一种新模式来匹配你想要提取的数值, 解构赋值就是采用了这种模式. 该模式会映射出你正在解构的数据结构,只有那些与该模式相匹配的数据,才会被提取出来. 被解构的数据项位于赋值运算符 = 的右侧,可以是任何数组和对象的组合,允许随意嵌套.用于给这些数据赋值的变量个数不限. 数组解构 数组解构 使用一个数组作为一个数据项,你可以根据 数组模式 (用于从数组中匹配

  • ES6新特性四:变量的解构赋值实例

    本文实例讲述了ES6新特性之变量的解构赋值.分享给大家供大家参考,具体如下: 1. 数组的解构赋值 //① 可以从数组中提取值,按照对应位置,对变量赋值 var [a, b] = [1, 2]; //a = 1;b = 2 //② 下面是一些使用嵌套数组进行解构 var [d, [[c], f]] = [1, [[2], 3]]; var [,,third] = ["foo", "bar", "baz"];//third = "baz&

  • ES6解构赋值实例详解

    本文实例讲述了ES6解构赋值.分享给大家供大家参考,具体如下: 基本用法 let [x, y, ...z] = ['a'] //"a", undefined, [] 1.等号右边如果不是数组,将会报错(不是可遍历结构) 2.解构赋值 var, let, const命令声明均适用 3.set结构也可解构赋值(具有Iterator接口,可采用数组形式结构赋值) set解构:任何类型的单个值的集合 let [x, y, z] = new Set(["a", "b

  • es6中的解构赋值、扩展运算符和rest参数使用详解

    前言 本文主要给大家介绍了关于es6中解构赋值.扩展运算符和rest参数使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. es6中较为常用的书写风格 为了书写的方便,es6中提出了很多比较友好的书写方式,其中最为常见的属于以下几个: 字符串模板 `abcdef${test}` 解构赋值 let [a, b, c] = [1, 2, 3] 扩展运算符 rest参数 ... 本文希望能够学习其中的主要的用法,方便书写和简洁性. 字符串模板 在以前的日子,我们经常捡到各

  • es6学习之解构时应该注意的点

    前言 本文主要给大家介绍了关于在es6解构时需要注意的一些事项,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 如果要将一个已经声明的变量用于解构赋值,必须非常小心. // 错误的写法 let x; {x} = {x: 1}; // SyntaxError: syntax error 上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误.只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题. //

  • ES6学习之变量的解构赋值

    变量的解构赋值 ES6中允许按照一定模式,从数组和对象中提取,对变量进行赋值. 数组的解构赋值 var [a,b,c] = [1,2,3]; a // 1; b // 2; c // 3; 上面的代码标示可以从数组中提取值,按照位置的对应关系对变量进行赋值. 本质上,这种写法属于"模式匹配",只要等号两边的模式相同,左边的变量就会被赋予对应的值. let [foo,[[bar],baz]] = [1,[[2],3]]; foo //1; bar //2; baz //3; let [,

  • ES6解构赋值的功能与用途实例分析

    本文实例讲述了ES6解构赋值的功能与用途.分享给大家供大家参考,具体如下: (1)交换变量的值 [x, y] = [y, x]; 上面代码交换变量x和y的值,这样的写法不仅简洁,而且易读,语义非常清晰. (2)从函数返回多个值 函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回.有了解构赋值,取出这些值就非常方便. // 返回一个数组 function example() { return [1, 2, 3]; } var [a, b, c] = example(); // 返

  • 解析JavaScript的ES6版本中的解构赋值

    什么是解构赋值? 解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性值赋给一系列变量.这个语法非常简洁,而且比传统的属性访问更加清晰. 在不使用解构赋值的情况下,访问数组的前三项: var first = someArray[0]; var second = someArray[1]; var third = someArray[2]; var first = someArray[0]; var second = someArray[1]; var third = someArray

  • 详解ES6 export default 和 import语句中的解构赋值

    解构赋值 有如下 config 对象 const config = { host: 'localhost', port: 80 } 要获取其中的 host 属性 let { host } = config 拆分成模块 以上两段代码,放到同一个文件当中不会有什么问题,但在一个项目中,config 对象多处会用到,现在把 config 对象放到 config.js 文件当中. // config.js export default { host: 'localhost', port: 80 } 在

  • Javascript中的解构赋值语法详解

    前言 首先在 ES6中引入的"解构赋值语法"允许把数组和对象中的值插入到不同的变量中.虽然看上去可能很难,但实际上很容易学习和使用. 解构赋值语法是一种 JS表达式.ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构.通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量. 在ES6解构赋值出现之前,我们需要为变量赋值的时候,只能直接指定值. 比如: let a = 1; let b = 2; let c = 3; let d = 4; let e

  • es6基础学习之解构赋值

    前言 es6的语法已经出了很长的时间了,在使用上也可以通过babel这类的编译工具转译为浏览器可以识别的es5的语法,但是依旧有很多开发在写代码的时候,依旧没有用es6的语法,而是习惯使用老的语法,这篇文章主要会介绍解构赋值基本用法以及在实际使用场景中相比es5语法的优势,让大家从根本上了解es6语法的优势 下面话不多说了,来一起看看详细的介绍吧 基本用法 数组解构 让我们一起先来看数组解构的基本用法: let [a, b, c] = [1, 2, 3] // a=1, b=2, c=3 let

  • JavaScript解构赋值的5个常见场景与实例教程

    目录 前言 1. 提取数据 2. 别名取值 3. 动态属性 4. 对象解构中的 Rest 5. 默认值 总结 前言 解构赋值语法是一种 JavaScript 表达式,通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量.这种语法是 ECMAscript 6 规范引入了一种新语法,可以更轻松地从数组和对象中获取值. 1. 提取数据 先来看看如何在 JavaScript 中解构对象,可以从这个商品对象的简单示例开始. const product = { id: 1, title: "Ni

  • JavaScript解构赋值的实用技巧指南

    目录 一.基本概念 二.解构分类 1. 对象的解构赋值 2. 数组的解构赋值 (1)字符串 (2)数组 (3)集合 (4)Map 三.嵌套解构 四.使用技巧 1. 函数解构 (1)解构函数参数 2. 循环中的解构 3. 动态属性解构 4. 交换变量 5. 数组拷贝 四.解构赋值注意点 总结 一.基本概念 为什么需要解构呢,先来看一个例子: const student = { name: 'ZhangSan', age: 18, scores: { math: 19, english: 85, c

  • ES6中let、const的区别及变量的解构赋值操作方法实例分析

    本文实例讲述了ES6中let.const的区别及变量的解构赋值操作方法.分享给大家供大家参考,具体如下: 声明:本文内容依照阮一峰老师ECMAScript 6 入门一书所总结. let和const 相同点 都存在块级作用域 都不存在变量声明提升 都会造成"暂时性死区" 在一个作用域下不可重复声明 不同点 const一旦声明必须立即赋值 const声明的变量指向的内存地址不得改动. 变量解构赋值 数组的解构赋值 解构成功 let [a, b, c] = [1, 2, 3]; 解构不成功

  • ES6中解构赋值实现变量批量赋值解放双手

    目录 引言 一.数组的解构赋值 解构失败 不完全解构 默认值 二.对象的解构赋值 三.字符串的解构赋值 结束语 引言 变量的解构赋值, 听起来很复杂, 简单点说可以理解成批量操作变量赋值,先有个印象, 下面慢慢来看 变量的解构赋值一共分为以下几种:数组的解构赋值 .对象的解构赋值 .字符串的解构赋值 . 一.数组的解构赋值 先来看一下我们平时对很多个变量赋值是如何操作的: let a = 1 let b = 2 let c = 3 let d = 4 那么我们看一下如何批量命名这些变量: let

  • 聊聊JS ES6中的解构

    概述 es6新增了一种从数组或者对象中获取指定元素的方式,这种方式就是我们今天要说的解构. 先来说说数组的解构 在有解构之前呢,我们获取数组中的指定元素通常是根据索引去做的: const arr = [1, 2, 3]; const a = arr[1]; 有了解构之后呢,我们便可以使用如下方式快速的去获取数组中的某个元素: const arr = [1, 2, 3]; const [a, b, c] = arr; console.log(a); console.log(b); console.

随机推荐