Javascript ES6 展开语法和解构赋值语法

1 篇文章 0 订阅

展开语法

展开语法(Spread syntax), 可以在函数调用或数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按键值的方式展开。

函数参数展开

function fun(a, b, c) {
    console.log(a, b, c)
}
let args = [1, 2, 3]
fun(...args)
// 1 2 3

function fun1(a, b, c, d) {
    console.log(a, b, c, d)
}
let args = [2, 3]
fun1(1, ...args, 4)
// 1 2 3 4

数组使用展开语法

let array1 = [1, 2, 3]
let array2 = ['hello', ...array1]
console.log(array2) // ["hello", 1, 2, 3]

数组的深拷贝

let array1 = [1, 2, 3]
let array2 = array1 
let array3 = [...array1]
array2.push(4);
array3.push(5)
console.log(array1) // [1, 2, 3, 4]
console.log(array2) // [1, 2, 3, 4]
console.log(array3) // [1, 2, 3, 5]

对象开展语法

let obj1 = { foo: 'bar', x: 42 }
let obj2 = { foo: 'baz', y: 13 }

let clonedObj = { ...obj1 } // 克隆后的对象: { foo: "bar", x: 42 }

let mergedObj = { ...obj1, ...obj2 } // 合并后的对象: { foo: "baz", x: 42, y: 13 }
扩展

剩余语法(剩余参数):

剩余语法(Rest syntax) 看起来和展开语法完全相同,不同点在于, 剩余参数用于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来并“凝聚”为单个元素。

function fun(a, b, ...theArgs) {
  console.log(a, b, theArgs)
}
fun(1, 2, 3, 4, 5) // 1 2 [3, 4, 5]

剩余参数和 arguments对象之间的区别主要有三个:

  • 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。

  • arguments对象不是一个真正的数组,而剩余参数是真正的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sortmapforEachpop

  • arguments对象还有一些附加的属性 (如callee属性)。

解构赋值

通过解构赋值, 可以将属性或值从对象或数组中取出,赋值给其他变量。

解构数组是将取值数组的元素与变量数据相对应,将数组中位置一致的值赋值给等号左边位置相同的变量。

解构对象是将相同键的对象相对应进行解构赋值。

let a, b, c
// 数组形式解构(解构数组) ↓
let [a, b] = [1, 2] // 变量声明并赋值时的解构
[a, b] = [1, 2] // 变量先声明后赋值时的解构
console.log(a, b) // 1 2
[a, b] = [1, 2, 3, 4]
console.log(a, b) // 1 2

[a, b, ...c] = [1, 2, 3, 4, 5]
console.log(a, b, c); // 1 2 [1, 2, 3, 4, 5]

// 对象形式结构(解构对象) ↓
let {a, b} = {a: 10, b: 20} // 声明解构赋值
console.log(a, b); // 10 20
({a, b} = {a: 10, b: 20}) // 无声明解构赋值
console.log(a, b); // 10 20
({a, b, ...c} = {a: 10, b: 20, c: 30, d: 40, e: 50}) // Rest剩余参数语法(展开语法)
console.log(a, b, c) // 10 20 {c: 30, d: 40, e: 50}

注意:

赋值语句周围的圆括号 ( ... ) 在使用对象无声明解构赋值时是必须的。

{a, b} = {a: 10, b: 20} 不是有效的独立语法,因为左边的 {a, b} 被认为是一个块而不是对象字面量。

然而,({a, b} = {a: 1, b: 2}) 是有效的,正如 var {a, b} = {a: 1, b: 2}

需要注意的是 ( ... ) 表达式之前需要有一个分号,否则它可能会被当成上一行中的函数执行。

let a, b
console.log('hello')
({a, b} = {a:1, b:2})
console.log(a, b)

// Uncaught TypeError: console.log(...) is not a function

以下是不正确的赋值方法:

// 错误的赋值方法 ↓
let c = {a: 1, b: true}
let a, b
{a, b} = c

// Uncaught SyntaxError: Unexpected token '='

// 正确的赋值方法 ↓
let c = {a: 1, b: true}
let {a, b} = c
// 或
let c = {a: 1, b: true}
let a, b
({a, b} = c)

如果 ( ... ) 表达式是没有声明时赋值的,则有无分号都无影响。

解构赋值中为了防止从数组取值为 undefined 提供里默认值,说白了就是为了防止变量数量少于取值数组数量时来为多余的变量赋予默认值

let a, b

[a, b] = [1]
console.log(a, b) // 1 undefined

[a, b=2] = [1]
console.log(a, b) // 1 2

let {a, b = 5} = {a: 1};
console.log(a, b); // 1 5

此外利用解构赋值语法可以更简便的交换变量

let a=1, b=2
console.log(a, b) // 1 2
[a, b] = [b, a]
console.log(a, b) // 2 1

忽略部分值

let a, b
[a,, b] = [1, 2, 3]
console.log(a, b) // 1 3

当然,你可以忽略所有值,不过这好像并没有什么意义

[,,] = [1, 2, 3]

解构对象给新的变量名赋值

let c = {a: 1, b: true};
let {a: foo, b: bar} = c;
 
console.log(foo, bar); // 1 true

解构对象给新的变量名赋值并提供默认值

var {a:foo, b:bar = 5} = {a: 3};
console.log(foo, bar); // 3 5
扩展

解构嵌套对象和数组

const metadata = {
  title: 'Scratchpad',
  translations: [
    {
      locale: 'de',
      localization_tags: [],
      last_edit: '2014-04-14T08:43:37',
      url: '/de/docs/Tools/Scratchpad',
      title: 'JavaScript-Umgebung'
    }
  ],
  url: '/en-US/docs/Tools/Scratchpad'
};

let {
  title: englishTitle, // rename
  translations: [
    {
       title: localeTitle, // rename
    },
  ],
} = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"

For of 迭代和解构

let people = [
  {
    name: 'Mike Smith',
    family: {
      mother: 'Jane Smith',
      father: 'Harry Smith',
      sister: 'Samantha Smith'
    },
    age: 35
  },
  {
    name: 'Tom Jones',
    family: {
      mother: 'Norah Jones',
      father: 'Richard Jones',
      brother: 'Howard Jones'
    },
    age: 25
  }
];

for (var {name: n, family: {father: f}} of people) {
  console.log('Name: ' + n + ', Father: ' + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"

从作为函数实参的对象中提取数据

function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

let user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"

从ECMAScript 2015开始,对象初始化语法开始支持计算属性名。其允许在[]中放入表达式,计算结果可以当做属性名。计算属性名可以被解构。

let key = "z";
let {[key]: foo} = {z: "bar"};

console.log(foo); // "bar"
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值