展开运算符、剩余参数、解构赋值

67 阅读5分钟

展开运算符、剩余参数、解构赋值

展开运算符

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

//函数调用中
function sum(x, y, z) {
  return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// Expected output: 6

//数组或字符串展开:
[...iterableObj, '4', ...'hello', 6];

//对象展开
let objClone = { ...obj };

展开语法就是把数组、字符串、对象等可迭代对象的所有值拿出来

特点

  • 数组、字符串、对象可以展开
  • 对象不能直接展开,必须在 {} 中展开

应用

  • 复制数组(函数参数为数组时常用)
//在js中,Array是引用类型,如果用arrA=arrB简单的把一个数组赋值,并没有创造出一个新数组,arrA和arrB其实指向的还是同一个地址,改变一个另一个也会随之改变
const arr = [1, 2 ,3];
const newArr = arr;
arr[0] = 3;
console.log(newArr); //=> [0,2,3]

//用展开语法
const arr = [1, 2 ,3];
const newArr = [...arr];
arr[0] = 3;
console.log(newArr);// => [1,2,3]
  • 数组拼接
const a = [1, 2];
const b = [3];
const c = [4, 5];

//可以指定数组的顺序
console.log([...a, ...b, ...c]);// =>[1, 2, 3, 4, 5]
console.log([...b, ...a, ...c]);// =>[3, 1, 2, 4, 5]
console.log([1, ...b, 2, ...a, ...c, 3]);// =>[1, 3, 2, 1, 2, 4, 5, 3]

  • 字符串转为字符串数组
//字符串转数组 在数组中展开字符串
const str = 'This is string'
console.log([...str]) // =>['T', 'h', 'i', 's', ' ', 'i', 's', ' ', 's', 't', 'r', 'i', 'n', 'g']
相当于console.log(str.split(''))

剩余参数

剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来并“凝聚”为单个元素

function(a, b, ...theArgs) {
  // ...
}

...theArgs即为剩余参数用法,theArgs数组将收集该函数的第三个参数和所有后续所有参数

特点

  • 是一个数组,可以用使用任意的数组方法
function sortRestArgs(...theArgs) {
    var sortedArgs = theArgs.sort();
    return sortedArgs;
}
  
console.log(sortRestArgs(5, 3, 7, 1)); // => [1,3,5,7]
  • 使用时就是个数组,不需要在前面加...
  • 剩余参数必须是最后一个参数 1698488298729.png

应用

  • 收集数量不确定的参数,比如说在防抖和节流中,用上剩余参数就可以使得防抖和节流函数应用于任何带或不带参数的函数
//防抖函数
function debounce(fn,delay){
    let t = null
    if(t){
        clearTimeout()
    }
    return funciton(...args){
        t=setTimeout(()=>{
            fn.apply(this,args)
        },delay)
    }
}

解构赋值

解构赋值语法是一种 Javascript 表达式。可以将数组中的值或对象的属性取出,赋值给其他变量。 (个人感觉展开语法就是把对象或数组解构了,获得了值,而展开赋值就多了一步,把取出的值付给了某个对应变量)
语法:

//有参数组 = 数组
const x = [1, 2, 3, 4, 5];
const [y, z] = x;
console.log(y); // 1
console.log(z); // 2

//有参对象 = 对象
const obj = { a: 1, b: 2 };
const { a, b } = obj;
// is equivalent to:
// const a = obj.a;
// const b = obj.b;

//等号左侧是待赋值的,等号右侧是待解构的,参数将会被赋值

特点

  • 数组与对象可用
  • 解构赋值可以用于提取对象中的嵌套属性和多层嵌套的数组元素

应用

解构数组

  • 基本变量赋值
const foo = ["one", "two"];

const [red, yellow, green, blue] = foo;
console.log(red); // "one"
console.log(yellow); // "two"
console.log(green); // undefined
console.log(blue); //undefined

  • 交换两个变量的值,不需要使用额外的临时变量。
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a); // 输出: 2
console.log(b); // 输出: 1
  • 获取和忽略函数返回值
function f() {
  return [1, 2, 3];
}

const [a, , b] = f();
console.log(a); // 1
console.log(b); // 3

const [c] = f();
console.log(c); // 1
  • 提取嵌套数组
let nestedArray = [1, [2, 3], 4, [5, [6, 7]]];

let [a, [b, c], d, [e, [f, g]]] = nestedArray;

console.log(a);  // 输出: 1
console.log(b);  // 输出: 2
console.log(c);  // 输出: 3
console.log(d);  // 输出: 4
console.log(e);  // 输出: 5
console.log(f);  // 输出: 6
console.log(g);  // 输出: 7

解构对象

  • 基本赋值
const user = {
  id: 42,
  isVerified: true,
};

const { id, isVerified } = user;

console.log(id); // 42
console.log(isVerified); // true

  • 从对象中提取属性,并将其赋值给名称与对象属性不同的变量
const o = { p: 42, q: true };
const { p: foo, q: bar } = o;

console.log(foo); // 42
console.log(bar); // true
//const { p: foo } = o 从对象 o 中获取名为 p 的属性,并将其赋值给名为 foo 的局部变量
  • 从作为函数参数传递的对象中提取属性(这个很重要,比如说封装了一个接口要在post请求中要传一个对象作为body参数,一开始我也没懂如何传参和为什么这么传,其实就是对象解构赋值)
//我们的对象如下:
const user = {
  id: 42,
  displayName: "jdoe",
  fullName: {
    firstName: "Jane",
    lastName: "Doe",
  },
};

function userId({ id }) {
  return id;
}
//这里参数这么写实际上是解构了user对象中的id属性并复制给了同名的id,这也就是第一点基本用法
console.log(userId(user)); // 42

function userDisplayName({ displayName: dname }) {
  return dname;
}
//这里我们提取名为 displayName 的属性,并将其重命名为 dname,以便在函数体内使用,这也是第二点从对象中提取属性,并将其赋值给名称与对象属性不同的变量
console.log(userDisplayName(user)); // `jdoe`

  • 解构嵌套对象
function whois({ displayName, fullName: { firstName: name } }) {
  return `${displayName} is ${name}`;
}

console.log(whois(user)); // "jdoe is Jane"
//属性 fullname.firstName被提取到名为name 的变量中

参考资料

玩转展开运算符 (zhihu.com)
展开语法 - JavaScript | MDN (mozilla.org)
Es6 解构赋值和扩展运算符_es6 结构赋值和扩展运算符-CSDN博客
展开运算符(...)的常见用法 - 简书 (jianshu.com)
es6: 数组与对象解构赋值 - 知乎 (zhihu.com)
ES6剩余参数和展开运算符 - 掘金 (juejin.cn)
剩余参数 - JavaScript | MDN (mozilla.org)
解构赋值 - JavaScript | MDN (mozilla.org)