你要知道的 - Spread Operator for objects 技巧

今天看到了你必须收藏的 ES6 语法密糖 - Spread Operator 技巧,这篇文章,收获很多,同时也想起来 ... 也有一些操作对象的用法,总结了一下。

在 ECMAScript 2018 中 Spread Operator 增加了对对象的支持,使得它的应用更为广泛,本文重点介绍如何将它与 Object 一起使用以及与 Object.assgin 的区别。

可以通过BABEL,查看示例代码 babel 编译后的结果。

... 解构赋值

除去已经声明的属性,剩余的所有属性都会赋给 ... 后的属性名

let { x, ...y } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // {y: 2, a: 3, b: 4}
复制代码
... 删除属性值

利用 ... 来删除对象中的某一个属性

let { x: deleted, ...y } = { x: 1, y: 2, a: 3, b: 4 };
console.log(y); // {y: 2, a: 3, b: 4}
复制代码
... 复制对象

在 JavaScript 中,有一个常见赋值语法如下

var cat = { age: 4 };
var kitten = cat;
kitten.age = 1;
复制代码

此时, catkitten 引用同一个对象,如果修改了 kitten 的属性,相应的 cat 也会发生变化。

console.log(kitten.age); // 1
console.log(cat.age); // 1 <-- problem!
复制代码

使用 Spread Operator 可以轻松地创建一个具有现有对象的所有相同属性的新对象。

const cat = { age: 4 };
const kitten = { ...cat }; // <-- changed
kitten.age = 1;

console.log(kitten.age); // 1
console.log(cat.age); // 4 <-- fixed!
复制代码

但是,利用 Spread Operator 去赋值对象,只能完成浅复制,也就是说利用 ... 去复制对象时,并不能递归地复制所有层级。

const cat = { age: 4, toys: ["mouse", "catnip"] };
const kitten = { ...cat };
// const kitten = Object.assign({}, cat); <-- same result
kitten.toys[1] = "yarn";
console.log(kitten.toys); // ["mouse", "yarn"]
console.log(cat.toys); // ["mouse", "yarn"] <-- problem!
复制代码
... 扩展对象

利用 ... 来拓展对象,就是将新属性添加到使用 Spread Operator 创建的对象上

const cat = { legs: 4 };
const dog = {
    ...cat,
    sound: "woof"
};
console.log(cat); // { legs: 4 }
console.log(dog); // { legs: 4, sound: "woof" }
复制代码

同样,可以看到 cat 对象未被更改,但新 dog 对象具有来自 catlegs 属性以及新 sound 属性,如果sound 已经存在的话,则会覆盖。

const cat = { legs: 4, sound: "meow" };
const dog = {
    ...cat,
    sound: "woof"
};
console.log(cat); // { legs: 4, sound: "meow" }
console.log(dog); // { legs: 4, sound: "woof" }
复制代码

但是,使用 ... 拓展对象时,要注意行顺序,也就是

const cat = { legs: 4, sound: "meow" };
const dog = {
    sound: "woof",
    ...cat
};
console.log(cat); // { legs: 4, sound: "meow" }
console.log(dog); // { legs: 4, sound: "meow" }
复制代码

上述 ...catsound: "woof" 改写为 sound: "meow"

...Object.assign 的区别

在上述利用 ... 处理对象的过程中,会发现 ... 有些时候与 Object.assgin 的操作近乎与等价的,那么他们具体的区别是什么。

Object.assign() 函数会触发 setters,而展开语法则不会*,具体的代码如下

const cat = {
  set feature(value) {
    console.log('set', value)
    this.features.push(value)
  },
  features: []
};

cat.feature = 'cute'; // log set cute

const dog = {
  feature: 'kind'
};

const monster = Object.assign(cat, dog); 
// 由于触发setters,则 log kind
const anotherMonster = { ...cat, ...dog };
// 无log
复制代码

上述代码中 monster

anotherMonster

显然 Spread Operator 没有对 setters 做处理,只是作为普通属性进行赋值。

参考

猜你喜欢

转载自juejin.im/post/5c35bd406fb9a049c84fa567
今日推荐