ES2015 数组与对象的解构

ECMAScript2015 新增了一种从数组或者对象获取指定元素的快捷方式,这是一种新的语法,这种新语法叫做解构。如下代码所示,定义一个数组:

const arr = [100, 200, 300]

const foo = arr[0]
const bar = arr[1]
const baz = arr[2]
console.log(foo, bar, baz)

在 ECMAScript2015 之前想要获取这个数组中的元素,需要通过索引访问对应的值,然后将访问的结果赋值给一个变量。

数组的解构

而在 ECMAScript2015 之后,可以通过数组的解构这种方式快速获取数组中的指定成员。如下代码所示:

const arr = [100, 200, 300]

const [foo, bar, baz] = arr
console.log(foo, bar, baz)

这时候就可以定义一个方括号,里面就是获取数组成员对应的变量名,这样变量名就会对应数组中的指定成员。如下图所示:

ES2015 数组与对象的解构_第1张图片

这里会根据变量的位置进行分配数组中对应位置的成员。如果只要获取某一个位置上的成员,比如上个数组中的最后一个位置的成员,只需要保留前两个占位就可以了。如下代码所示:

const arr = [100, 200, 300]

const [, , baz] = arr
console.log(baz)

这里需要注意的是,要确保解构的位置和数组的结构是一致的,才可以正确得到对应的成员。

除此之外,还可以在变量名前面增加 ... 来获取从当前位置到数组最后的所有成员。如下代码所示:

const arr = [100, 200, 300]

const [foo, ...rest] = arr
console.log(rest)

上述代码的运行结果如下:

[ 200, 300 ]

从打印的结果可以看到,这种做法会将所有的成员存储在一个新的数组当中。

这里需要注意的是,这种解构的用法只能在成员变量的最后一个变量上才能使用。

如果解构的变量数量少于数组的成员数量的话,那会按照从前到后的顺序进行获取。如下代码所示:

const arr = [100, 200, 300]

const [foo] = arr
console.log(foo)

上述代码的运行结果如下:

100

从打印的结果可以看到,数组中剩下的成员都不会被获取到。反之,如果解构的变量数量多于数组的成员数量的话,那多出来的变量的值为 undefined。如下代码所示:

const arr = [100, 200, 300]

const [foo, bar, baz, more] = arr
console.log(more)

上述代码的运行结果如下:

undefined

这个结果和访问数组中不存在的索引值的结果是一致的。

如果想要为解构的变量设置默认值,这种语法也是支持的。如下代码所示:

const arr = [100, 200, 300]

const [foo, bar, baz, more = 'default value'] = arr
console.log(more)

上述代码的运行结果如下:

default value

如果解构中的变量没有获取到数组中对应位置的成员,那这个变量将是默认值。

数组中的解构在很多的应用场景中会带来很大的便捷,比如拆分一个字符串,然后获取拆分之后的指定位置。如下代码所示:

const path = 'foo/bar/baz'

const tmp = path.split('/')
const rootDir = tmp[1]
console.log(rootDir)

上述代码是 ECMAScript2015 之前需要一个临时变量来存储拆分字符串之后的结果,但使用 ECMAScript2015 之后的解构将大大进行简化。如下代码所示:

const path = 'foo/bar/baz'

const [, rootDir] = path.split('/')
console.log(rootDir)

对象的解构

在 ECMAScript2015 中,除了数组可以被解构之外,对象同样也可以被解构。只不过对象的解构,是需要通过属性名来获取,而不是位置。如下代码所示:

const obj = {
  name: '前端课湛',
  age: 3
}

const {
  name
} = obj
console.log(name)

上述代码的运行结果如下:

前端课湛

这里解构中的变量名还有一个很重要的作用,就是匹配解构对象中的成员,从而获取指定成员的值。比如上述代码结构总的 name 获取了 obj 对象中的 name 属性值。

因为对象的解构的这种特性,如果当前作用域中存在一个同名的变量,就会产生冲突。如下代码所示:

const obj = {
  name: '前端课湛',
  age: 3
}

const name = '大前端'
const {
  name
} = obj
console.log(name)

上述代码的运行结果如下:

object-destructuring.js:13
  name
  ^

SyntaxError: Identifier 'name' has already been declared
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:599:28)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Function.Module.runMain (module.js:676:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3

因为 obj 对象的 name 属性必须在解构中定义 name 变量进行获取,那么这一冲突就无法避免。这个时候可以通过重命名的方式来解决这样的问题,如下代码所示:

const obj = {
  name: '前端课湛',
  age: 3
}

const name = '大前端'
const {
  name: objName
} = obj
console.log(objName)

如上述代码所示,解构中原本的 name 对应着 obj 对象的 name 属性,objName 是重命名的变量名,从而解决了同名的冲突。如下图所示:

ES2015 数组与对象的解构_第2张图片

除了上述的情况之外,对象的解构和数组的解构的用法基本上是一致的,比如没有对应的属性的话会得到 undefined、可以设置默认值等等。

对象的解构的应用场景比数组的解构只多不少,不过大部分的场景都是为了简化代码。比如代码中大量的使用了 console.log() 方法,就可以先把 log() 方法解构出来再进行使用。如下代码所示:

const {
  log
} = console
log('foo')
log('bar')
log('baz')

你可能感兴趣的:(大前端高薪训练营,#,ECMAScript2015,新特性)