var { foo } = {bar: 'baz'}
console.log(foo) //<- undefined
如果尝试去访问对象一个不存在的深嵌套的属性,将会得到一个异常。
var {foo: {bar}} = {baz: 'ouch'} //<- Exception Cannot read property 'bar' of undefined
如果你知道她只是在ES5上进行了一层语法的包装,你将好理解很多
var _tmp = { baz: 'ouch' }
var bar = _temp.foo.bar //<- Exception
解构有个非常酷的特性她允许你不用通过中间变量来交换变量之间的值。
function es5() {
var left = 10
var right = 20
var aux
if (right > left) {
aux = right
right = left
left = aux
}
}
function es6() {
var left = 10
var right = 20
var aux
if (right > left ) {
[ right, left ] = [ left, right ]
}
}
function greet ({age, name:greeting='she'}) {
consol.log(`${greeting} is ${age} years old.`)
}
greet({name: 'nico', age: 27}) //<- 'nico is 27 years old'
greet({age: 24}) //<- 'she is 24 years old'
[译]ES6 JavaScript Destructuring in Depth
@(javascript)[ES6 JavaScript in Depth | javacript| 翻译]
这篇文章将专注于讨论ES6中的语言特性。以ES6中的最为有用,同时也存在一些陷阱的解构开始,我们之后将开一个系列文章来讨论ES6。
简短的声明
当在不确定和有选择的情况下,你可能还是应该使用ES5和老的语法而不是因为你知道ES6就是用ES6。然而我并不是说是用ES6的语法是一种错误的方法--恰恰相反,你正看到我写关于ES6的文章。我提倡的是基于这样一个事实,确定她一定能提高我们代码的质量的时候才使用ES6, 而仅仅是因为她时一个
酷玩意儿
--虽然她是。到目前为止,我所说的观点是用ES5来写东西,加上一些ES6的语法糖在上面将确切的改善我的代码。我推测在不久后我能快速的意识到某些场景下使用ES6是优于ES5的,但是在目前紧跟着学习她是一个不错的主意,而不要走得太极端。谨慎分析什么是最适合你的代码,并且心里记着可以有ES6这个新的选择就行。
现在就来看看ES6中的新特性把!
解构
这是ES6中最简单,也是我使用的最多的一个特性。她可以绑定属性到你需要的任意多的变量上面,并且她支持数组和对象。
她可以十分高效的将指定属性从一个对象中解构出来。你也可以使用映射属性到一个别名。
你也可以把属性放到任意深的位置,并且完成别名的绑定。
默认的,没有找到的对应的属性的值将使
undefined
, 就像你通过.
或者[]
访问一个对象中不存在的属性一样。如果尝试去访问对象一个不存在的深嵌套的属性,将会得到一个异常。
如果你知道她只是在ES5上进行了一层语法的包装,你将好理解很多
解构有个非常酷的特性她允许你不用通过中间变量来交换变量之间的值。
另外一个方便的部分是解构可以让
keys
使用表达式。在ES5中,你要实现的话需要而外的语句和变量声明
你可以为变量指定默认值,当解构出来的属性值为
undefined
的时候,比较有用。解构同样对数组有效,且看我用中括号在声明语句中解构数组
并且我们同样可以使用相同的规则指定默认值
当是数组的时候你还可以方便的忽略某些你不关心的元素
同样你可以在函数的参数列表中使用解构
以上是你可以怎样使用解构的一个粗略的介绍,那解构一般用于什么场景呢?
解构的使用场景
解构用各种使用场景,这个是最常见的一个,当你有个返回对象的方法时,解构可以通过十分简便的方法提取返回值
另一个相似的但是相反的是使用结构为函数的一大串参数定义默认值,这个十分有趣,她实现了在其他语言如
Python
和C#
中的命名参数。如果你想让形参完全是可选的,你可以改变写法如下
解构还非常适用在正则表达式中,当你想给一些缺乏索引的值指定变量的时候,这里有一个解析URL的随机正则的例子,我在StackOverflow中发现的。
特殊的情景:
import
语句 尽管import
语句不遵从解构的规则,但是表现有点类似。这可能是我使用的比较多的跟结构类似的场景, 尽管不是真正的解构。当你使用import
你可以从一个模块暴露的API中获取任何你需要的值。一个使用contra
的例子:注意,尽管,
import
语句有不同的语法,当对比解构,下列import
声明没有一个是有效的。import { series = noop } from 'contra'
import {map: { series }} from 'contra'
import {map: mapAsync} from 'contra'
以上限制的主要的原因是
import
声明自带绑定的,不是引用或者值,这是非常重要的区别,我们将在之后的in depth
关于ES6 modules的文章探讨。