ES6的扩展运算符(三个点)和解构赋值的用法

来源:程序思维浏览:3435次
展开语法

展开语法(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实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach或pop。

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"
精品好课
HTML5基础入门视频教程易学必会
HTML5基础入门视频教程,教学思路清晰,简单易学必会。适合人群:创业者,只要会打字,对互联网编程感兴趣都可以学。课程概述:该课程主要讲解HTML(学习HTML5的必备基础语言)、CSS3、Javascript(学习...
最新完整React+VUE视频教程从入门到精,企业级实战项目
React和VUE是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React和VUE并应用到实战,教你如何解决内存泄漏,常用库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习Re...
React实战视频教程仿京东移动端电商
React是前端最火的框架之一,就业薪资很高,本课程教您如何快速学会React并应用到实战,对正在工作当中或打算学习React高薪就业的你来说,那么这门课程便是你手中的葵花宝典。
HTML5视频播放器video开发教程
适用人群1、有html基础2、有css基础3、有javascript基础课程概述手把手教你如何开发属于自己的HTML5视频播放器,利用mp4转成m3u8格式的视频,并在移动端和PC端进行播放支持m3u8直播格式,兼容...
Vue2+Vue3+ES6+TS+Uni-app开发微信小程序从入门到实战视频教程
2021年最新Vue2+Vue3+ES6+TypeScript和uni-app开发微信小程序从入门到实战视频教程,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己...
jQuery视频教程从入门到精通
jquery视频教程从入门到精通,课程主要包含:jquery选择器、jquery事件、jquery文档操作、动画、Ajax、jquery插件的制作、jquery下拉无限加载插件的制作等等......
最新完整React视频教程从入门到精通纯干货纯实战
React是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习React高薪就...
VUE2+VUE3视频教程从入门到精通(全网最全的Vue课程)
VUE是目前最火的前端框架之一,就业薪资很高,本课程教您如何快速学会VUE+ES6并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习VUE高薪就...
收藏
扫一扫关注我们