变量的解构赋值

2017-09-25  本文已影响0人  CandyTong_

标签: ES6


  • ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值
  • 本质上属于“模式匹配”,只要等号两边模式相同,左边的变量就会被赋予相应的值

数组的解构赋值

基本用法

var [a, b, c] = [1, 2, 3]
a   // 1
b   // 2
c   // 3
let [x, y] = [1, 2, 3]
x   // 1
y   // 2

对于数组解构赋值,如果等式右边不是可遍历结构(本身 / 转化后的对象具备Iterator接口),将会报错

// 报错,转化后的对象不具备Iterator接口
let [a] = 1
let [b] = false
// 报错,对象本身不具备Iterator接口
let [c] = {}        
// 解构成功,字符串能转换成类似数组的对象
let [d, e, f, g, h] = 'hello'

默认值

var [x, y = 2] = [1]    // x=1,y=2
var [x = 1] = [undefined]   // x=1
var [y = 1] = [null]        // y=null,默认值不生效
由于`(null===undefined)`的值为false,所以默认值不生效,`y`的值为null
function f() {
    console.log(123)
}
let [x = f()] = [1]     // 无输出
let [x = 1, y = x] = []     // x=1,y=1
let [a = b, b = 1] = []     // 报错

对象的解构赋值

基本用法

var { foo, bar } = { foo: 123, bar: 345 }
foo // 123
bar // 345
var { abc } = { foo: 123, bar: 345 }
abc // undefined

对象的解构赋值实际上是以下形式的简写

var { foo, bar } = { foo: 123, bar: 345 }   // 简写
var { foo: foo, bar: bar } = { foo: 123, bar: 345 }

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

var { foo: baz } = { foo: 123, bar: 345 }
baz // 123
foo // Error:foo is not defined

对一个已经声明的变量解构赋值,不能将大括号 { } 写在行首,避免 javascript 将其解析为代码块

var x
({ x } = { x: 1 })  // 正确写法
{ x } = { x: 1 }    // 错误写法

默认值

默认值生效的条件是,对象的属性严格等于undefined

var { message: msg = 123, x } = { message: undefined, x: null }
msg     // 123
x       // null

解构嵌套结构的对象

var node = {
    loc: {
        start: {
            line: 1,
            column: 5
        }
    }
}
var { loc: { start: { line, column } } } = node
line    // 1
column  // 5
loc     // Error
start   // Error

注意:loc 和 start 是模式,不是变量,因此不会被赋值

解构对象是嵌套的对象,而且子对象所在的父对象不存在,会报错

var { foo: { bar } } = {}

foo为父对象,bar为子对象,foo不存在,报错
原因很简单:foo这时为undefined,再取子属性bar就会报错

其他类型的解构赋值

字符串的解构赋值

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

let [d, e, f, g, h] = 'hello'
var { length: len } = 'hello'
len     // 5

数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值或布尔值,则先转为对象
undefinednull无法转为对象,会报错

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

函数参数的解构赋值

function add([x, y]) {
    return x + y
}
add([1, 2])     // 3

注意区分以下两种情况:

function move({ x = 0, y = 0 } = {}) {
    return [x, y]
}
move({ x: 3, y: 1 })    // { x: 3, y: 1 }
move({ x: 3})           // { x: 3, y: 0 }
move({})                // { x: 0, y: 0 }
move()                  // { x: 0, y: 0 }

为解构设置默认值,当解构失败时使用默认值
move()使用了函数默认值{},然后解构,解构失败,使用解构默认值

function move({} = { x = 0, y = 0 }) {
    return [x, y]
}
move({ x: 3, y: 1 })    // { x: 3, y: 1 }
move({ x: 3})           // { x: 3, y: undefined }
move({})                // { x: undefined, y: undefined }
move()                  // { x: 0, y: 0 }

为函数设置默认值,仅当函数没有传参的时候才使用默认值
move({})传入了空对象,所以没有使用函数默认值{},接下来是解构,解构失败,由于没有解构默认值,其值为undefined

变量解构的用途

交换变量的值

[x, y] = [y, x]

从函数返回多个值

function example() {
    return [1, 2, 3]
}
var [a, b, c] = example()
function example() {
    return {
        foo: 1,
        bar: 2
    }
}
var { foo, bar } = example()

函数参数的定义

// 参数是一组有次序的值
function f([x, y, z]) {  ...  }
f([1, 2, 3])
// 参数是一组无次序值
function f({ x, y, z }) {  ...  }
f({ z: 1, y: 2, x: 3 })

提取JSON数据

var jsonData = {
    id: 1,
    is_error: false,
    result: [123, 456]
}
let { id, is_error, result } = jsonData

函数参数的默认值

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

遍历Map结构

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

var map = new Map()
map.set('first', 'hello')
map.set('second', 'world')
for (let [key, value] of map) {
    console.log(key, value)
}
// first hello
// second world

输出模块的指定方法

const { SourceMapConsumer, SourceNode } = require("source-map")
上一篇下一篇

猜你喜欢

热点阅读