美文网首页
变量的解构赋值

变量的解构赋值

作者: CandyTong_ | 来源:发表于2017-09-25 20:15 被阅读0次

    标签: ES6


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

    数组的解构赋值

    基本用法

    var [a, b, c] = [1, 2, 3]
    a   // 1
    b   // 2
    c   // 3
    
    • 解构不成功,则解构不成功的变量的值为undefined
    • 不完全解构,即等号左边的模式只匹配等号右边数组的一部分,则解构依然成功
    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
    
    • 使用严格相等运算符(===)判断一个位置是否有值,仅在严格等于undefined时,默认值生效
    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")
    

    相关文章

      网友评论

          本文标题:变量的解构赋值

          本文链接:https://www.haomeiwen.com/subject/aagdextx.html