假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
当前回答
对象。当目标对象是一个常量并且您希望一次设置多个属性时,Assign是必要的。
例如:
const target = { data: "Test", loading: true }
现在,假设你需要用一个源的所有属性来改变目标:
const source = { data: null, loading: false, ...etc }
Object.assign(target, source) // Now target is updated
target = { ...target, ...source) // Error: cant assign to constant
请记住,您正在改变目标obj,所以尽可能使用Object。分配空目标或扩散分配给一个新的obj。
其他回答
当你必须使用Object.assign时,我想添加这个简单的例子。
class SomeClass {
constructor() {
this.someValue = 'some value';
}
someMethod() {
console.log('some action');
}
}
const objectAssign = Object.assign(new SomeClass(), {});
objectAssign.someValue; // ok
objectAssign.someMethod(); // ok
const spread = {...new SomeClass()};
spread.someValue; // ok
spread.someMethod(); // there is no methods of SomeClass!
使用JavaScript时可能不清楚。但是如果你想创建一些类的实例,使用TypeScript会更容易
const spread: SomeClass = {...new SomeClass()} // Error
这并不一定详尽无遗。
传播的语法
options = {...optionsDefault, ...options};
优点:
如果在没有本机支持的环境中编写代码以执行,则可以只编译此语法(而不是使用polyfill)。(比如巴别塔。) 可以减少复杂性。
缺点:
当这个答案最初被写出来的时候,这是一个建议,没有标准化。在使用提案时,请考虑如果您现在使用提案编写代码,而它没有得到标准化或在向标准化发展的过程中发生变化,该怎么办。这已经在ES2018中标准化了。 字面的,不是动态的。
Object.assign ()
options = Object.assign({}, optionsDefault, options);
优点:
标准化。 动态的。例子: var sources = [{a: " a "}, {b: " b "}, {c: " c "}]; options = Object.assign。应用(对象,({}).concat(来源)); / /或 options =对象。分配({},…来源);
缺点:
更详细的。 如果在没有本机支持的环境中编写代码执行,则需要填充。
这是让我疑惑的承诺。
这和你问的问题没有直接关系。这段代码没有使用Object.assign(),而是使用用户代码(object-assign)来做同样的事情。他们似乎在用Babel编译代码(并将其与Webpack捆绑),这就是我所说的:你可以编译的语法。他们显然更喜欢这样,而不是必须将对象赋值作为一个依赖项包含到他们的构建中。
这现在是ES6的一部分,因此是标准化的,并且在MDN上也有文档: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
它使用起来非常方便,与对象解构一起使用也很有意义。
上面列出的另一个优势是object. assign()的动态功能,不过这就像在文字对象中展开数组一样简单。在编译后的babel输出中,它完全使用了Object.assign()所演示的内容
因此,正确的答案是使用object spread,因为它现在是标准化的,被广泛使用(参见react, redux等),易于使用,并且具有object .assign()的所有特性。
作为参考,对象rest/spread在ECMAScript 2018中作为第4阶段完成。提案可以在这里找到。
在大多数情况下,对象赋值和扩展的工作方式是相同的,关键的区别是扩展定义属性,而object .assign()设置属性。这意味着Object.assign()触发设置器。
值得记住的是,除此之外,对象rest/spread 1:1映射到object .assign(),与数组(可迭代)spread的作用不同。例如,当展开一个数组时,将展开空值。然而,使用对象传播时,空值会被无声地传播到空值。
数组(可迭代)扩展示例
const x = [1, 2, null , 3];
const y = [...x, 4, 5];
const z = null;
console.log(y); // [1, 2, null, 3, 4, 5];
console.log([...z]); // TypeError
对象扩展示例
const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};
console.log(z); //{a: 1, b: 2}
这与Object.assign()的工作方式是一致的,两者都无声地排除空值而没有错误。
const x = null;
const y = {a: 1, b: 2};
const z = Object.assign({}, x, y);
console.log(z); //{a: 1, b: 2}
注意:Spread不仅仅是Object.assign的语法糖。它们在幕后的运作方式大不相同。
对象。assign对新对象应用setter,而Spread则不会。此外,对象必须是可迭代的。
复制 如果您需要对象当前的值,并且不希望该值反映该对象的其他所有者所做的任何更改,则使用此选项。
使用它创建对象的浅拷贝 始终将不可变属性设置为copy的好做法——因为可变版本可以传递到不可变属性中,copy将确保您始终处理不可变对象
分配 赋值在某种程度上与复制相反。 Assign将生成一个setter,它将值直接赋给实例变量,而不是复制或保留它。 当调用赋值属性的getter时,它返回一个对实际数据的引用。