JavaScript ES(6-11)全版本语法 (二):解构赋值

815 阅读5分钟

前提概要

由于从上周刚开始写文章,在这立了flag,坚持一周至少写一篇关于ES语法的文章,来提高自己的基础。
上一篇写的是ES6中新的声明方式,链接:juejin.cn/post/699405… ,这次写的是ES6中解构赋值。如有不对的或者不准确的地方,欢迎大家提出😄,我也积极修改。下边开始正文:

673083c0-c288-45cf-b9ff-b4cca036039c.jpg

正文

在ES6中新增了变量赋值的方式:解构赋值。允许按照一定模式,从数组和对象中提取值,对变量进行赋值。代码如下:

let arr = [1,2,3]
let a = arr[0]
let b = arr[1]
let c = arr[2]

上述代码中,声明一个数组arr,从数组中依次取值,赋值给 a,b,c 三个变量,在ES6中可以这样写

let [a,b,c] = [1,2,3]

TIP
解构赋值重点是在赋值,赋值的元素是要拷贝出来赋值给变量,赋值的元素本身是不会被改变的。

在解构赋值里用的最多的就是 Object 和 Array ,下面我们看一下两者的解构赋值是如何操作的。

数组解构赋值

  • 赋值元素可以是任意可遍历的对象
    赋值的元素不仅是数组,它可以是任意可遍历的对象
    let [a,b,c] = 'abc'
    console.log(a,b,c) // 'a' 'b' 'c' 
    
    let [x,y,z] = new Set([1,2,3])
    console.log(a,b,c) // 1 2 3
    
  • 左边的变量
    被赋值的变量还可以是对象的属性,不局限于单纯的变量。
      let user = {}
      [user.firstName, user.secondName, user.thirdName] = '谢 大 脚'.split(' ')
      console.log(user.firstName, user.secondName, user.thirdName) // 谢 大 脚
      console.log(user) // {firstName: "谢", secondName: "大", thirdName: "脚"}
    
  • 循环体
    解构赋值在循环体中的应用,可以配合 entries 使用。
    let user = {
      name:'刘能',
      like:'逗谢广坤'
    }
    for(let [key,value] of Object.entries(user)){
      console.log(`${key}:${value}`) // name:刘能  like:逗谢广坤
    }
    
  • 可以跳过赋值元素
    如果想忽略数组的某个元素对变量进行赋值,可以使用逗号来处理。
    let [name,,age] = ['xs','boy',18,'guitar']
    console.log(age) // 18
    
  • rest 参数
    let [name,age,...rest] = ['xs',18,'boy','guitar']
    console.log(name) // 'xs'
    console.log(age) // 18
    console.log(rest) //['boy','guitar']
    console.log(rest[0]) // 'boy'
    console.log(rest[1]) // 'guitar'
    console.log(rest.length) // 2
    

    注意
    我们可以使用 rest 来接受赋值数组的剩余元素,不过要确保这个 rest 参数是放在被赋值变量的最后一个位置上。

  • 默认值
    如果数组的内容少于变量的个数,并不会报错,没有分配到内容的变量会是 undefined。
    let [name ,age] = []
    console.log(name) // undefined
    console.log(age) // undefined
    
    let [a, b, c] = [1, 2]
    console.log(a, b, c)// 1  2  undefind
    
    当然你也可以给变量赋予默认值,防止 undefined 的情况出现:
    let [name = 'xs', age = 18] = ['Kobe Bryant']
    console.log(name) // 'Kobe Bryant'
    console.log(age) // 18
    

理解
通过例子可以看出数组的解构赋值是 惰性赋值,当你赋值的时候会取赋的值,不赋值的时候会取默认的值,如果默认的值没有会默认为undefind。所以可以证明数组的赋值是根据数组的下标的index值进行赋值

下面例子验证是数组赋值是惰性赋值

function foo () {
  console.log(123)
}

let [a = foo()] = [1]

上述代码中,当右侧赋值的数组中存在元素1时,控制台是不会输出函数foo中打印的123,如果右侧赋值的数组是一个空数组[],则控制台是输出函数foo中打印的123。因此,可以验证是数组赋值是惰性赋值。

对象解构赋值

  • 基本用法
    解构赋值除了可以应用在 Array,也可以应用在 Object。基本的语法如下:

    let {var1, var2} = {var1:…, var2…}

    意思是我们声明一个Object,想把里面的属性分别拿出来而无需通过调用属性的方式赋值给指定的变量。具体的做法是在赋值的左侧声明一个和Object结构等同的模板,然后把需要的属性的value指定为新的变量即可。

    let obj = {
      name: 'xs',
      age: 18,
      like: 'music'
    }
    let { name, age, like } = obj
    console.log(name) // 'xs'
    console.log(age) // 18
    console.log(like) // 'music'
    

    TIP
    在这个结构赋值的过程中,左侧的“模板”结构要与右侧的Object一致,但是属性的顺序无需一致。

    上述的赋值左侧是采用了对象简写的方式,类似于:

    let {name: name, age: age, like: like} = obj
    

    如果不想这么写或者想使用其他的变量名,可以自定义的,如下:

    let {name: uname, age: uage, like} = obj
    
  • 默认值 赋值的过程中也是可以指定默认值的,如下:

    let obj = {
      name: 'xs',
    }
    let {name,age = 18,like='music'} = obj
    console.log(name) // 'xs'
    console.log(age) // 18
    console.log(like) // 'music'
    
  • rest 运算符
    如果你只需要指定的属性,其他可以暂存到一个变量中,这就要用到rest运算符

    let obj = {
      name: 'xs',
      age: 18,
      like: 'music'
    }
    let { name, ...rest} = obj
    console.log(name) // 'xs'
    console.log(rest) // {age: 18,like: 'music'}
    
  • 嵌套对象
    如果一个 Array 或者 Object 比较复杂,它嵌套了 Array 或者 Object,那只要被赋值的结构和右侧赋值的元素一致就好了。

    let obj = {
      userName: 'xs',
      age: 18,
      like: {
        type:'sports',
        likeName:'basketball'
      },
      music:['Light music','rock music'],
    }
    let {
      userName,
      age,
      like: {
        type,
        likeName
      },
      music:[type1,type2],
      sex='male'
    } = obj
    console.log(type) // 'sports'
    console.log(likeName) // 'basketball'
    console.log(type1) // 'Light music'
    console.log(type2) // 'rock music'
    console.log(sex) // 'male'
    

字符串解构赋值

字符串的解构赋值可按照数组的解构赋值理解

let str = 'string'
for (let i = 0; i < str.length; i++) {
  console.log(str[i])
}

等同于如下代码所示:

let [a, b, c, d, e, f] = 'string'
console.log(a, b, c, d, e, f)

函数的解构赋值

  • 函数参数为数组的解构赋值
    function foo ([a, b, c]) {
      console.log(a, b, c) // 1  2  3
    }
    let arr = [1, 2, 3]
    foo(arr)
    
  • 函数参数为对象的解构赋值
    function foo ({ name, age , sex='male'}) {
      console.log(name, age) // 'xs'  18
    }
    let obj = {
      name: 'xs',
      age: 18
    }
    foo(obj)
    
    上述代码中的sex属性为可传可不传的属性,如果不传值则默认为'male',如果传值,则取所传的值。
  • 对函数返回值的解构赋值
    function foo ([a, b, c]) {
      let obj = {
        name: 'xs',
        age: 18,
        school:'xxx'
      }
      return obj
    }
    let {name,age,school} = foo()
    console.log(name,age,school) // 'xs' 18 'xxx'
    

JSON数据的解构赋值

JSON数据的解构赋值可按照对象的解构赋值理解

let json = '{"a":"hello","b":"world"}'
let { a, b } = JSON.parse(json)
console.log(a, b) // 'hello' 'world'