假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
当前回答
我们将创建一个名为identity的函数,它只返回我们给它的任何参数。
identity = (arg) => arg
和一个简单的数组。
arr = [1, 2, 3]
如果用arr求恒等函数,我们知道会发生什么
其他回答
我想总结一下“扩展对象合并”ES特性在浏览器和工具生态系统中的状态。
Spec
https://github.com/tc39/proposal-object-rest-spread 这个语言特性是第4阶段的提案,这意味着它已经被合并到ES语言规范中,但还没有被广泛实现。
浏览器:Chrome, SF, Firefox(60版本,IIUC)
浏览器支持Chrome 60中附带的“传播属性”,包括这个场景。 在当前的Firefox(59)中不支持此场景,但在我的Firefox开发者版中可以。所以我相信它会在Firefox 60中发布。 Safari:未测试,但Kangax说它可以在桌面Safari 11.1中运行,但不适用于SF 11 iOS Safari:未测试,但Kangax说它可以在iOS 11.3运行,但不能在iOS 11运行 还没有在Edge中
工具:Node 8.7, TS 2.1
NodeJS从8.7开始支持(通过Kangax)。9.8在本地测试时确认。 TypeScript从2.1开始支持它,目前是2.8
链接
Kangax“财产蔓延” https://davidwalsh.name/merge-objects
代码示例(兼作兼容性测试)
var x = { a: 1, b: 2 };
var y = { c: 3, d: 4, a: 5 };
var z = {...x, ...y};
console.log(z); // { a: 5, b: 2, c: 3, d: 4 }
再次强调:在编写此示例时,无需编译即可在Chrome(60+)、Firefox Developer Edition (Firefox 60预览版)和Node(8.7+)中工作。
为什么答案?
我是在最初的问题提出两年半后写这篇文章的。但我也有同样的问题,谷歌让我来这里。我是SO改善长尾理论使命的奴隶。
Since this is an expansion of "array spread" syntax I found it very hard to google, and difficult to find in compatibility tables. The closest I could find is Kangax "property spread", but that test doesn't have two spreads in the same expression (not a merge). Also, the name in the proposals/drafts/browser status pages all use "property spread", but it looks to me like that was a "first principal" the community arrived at after the proposals to use spread syntax for "object merge". (Which might explain why it is so hard to google.) So I document my finding here so others can view, update, and compile links about this specific feature. I hope it catches on. Please help spread the news of it landing in the spec and in browsers.
最后,我本可以将这些信息作为评论添加进来,但我无法在不破坏作者原始意图的情况下编辑它们。具体来说,我无法编辑@ chillpenguin的评论,否则它就会失去纠正@RichardSchulte的意图。但多年后,理查德(在我看来)证明是对的。所以我写了这个答案,希望它最终能取代旧的答案(可能需要几年时间,但毕竟这就是长尾效应的意义所在)。
其他答案都老了,得不到好的答案。 下面的例子是对象字面量,有助于两者如何相互补充,以及如何不能相互补充(因此存在差异):
var obj1 = { a: 1, b: { b1: 1, b2: 'b2value', b3: 'b3value' } };
// overwrite parts of b key
var obj2 = {
b: {
...obj1.b,
b1: 2
}
};
var res2 = Object.assign({}, obj1, obj2); // b2,b3 keys still exist
document.write('res2: ', JSON.stringify (res2), '<br>');
// Output:
// res2: {"a":1,"b":{"b1":2,"b2":"b2value","b3":"b3value"}} // NOTE: b2,b3 still exists
// overwrite whole of b key
var obj3 = {
b: {
b1: 2
}
};
var res3 = Object.assign({}, obj1, obj3); // b2,b3 keys are lost
document.write('res3: ', JSON.stringify (res3), '<br>');
// Output:
// res3: {"a":1,"b":{"b1":2}} // NOTE: b2,b3 values are lost
这里还有几个小例子,同样是数组和对象: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
这并不一定详尽无遗。
传播的语法
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捆绑),这就是我所说的:你可以编译的语法。他们显然更喜欢这样,而不是必须将对象赋值作为一个依赖项包含到他们的构建中。
当你必须使用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
正如其他人所提到的,在撰写本文时,object .assign()需要一个polyfill和object spread…需要一些蒸煮(也许是一个填充)为了工作。
考虑下面的代码:
// Babel wont touch this really, it will simply fail if Object.assign() is not supported in browser.
const objAss = { message: 'Hello you!' };
const newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);
// Babel will transpile with use to a helper function that first attempts to use Object.assign() and then falls back.
const objSpread = { message: 'Hello you!' };
const newObjSpread = {...objSpread, dev: true };
console.log(newObjSpread);
它们都产生相同的输出。
下面是从Babel到ES5的输出:
var objAss = { message: 'Hello you!' };
var newObjAss = Object.assign(objAss, { dev: true });
console.log(newObjAss);
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var objSpread = { message: 'Hello you!' };
var newObjSpread = _extends({}, objSpread, { dev: true });
console.log(newObjSpread);
这是我目前的理解。object .assign()实际上是标准化的,其中随着对象扩展…还没有。唯一的问题是浏览器对前者以及未来对后者的支持。
玩一下这里的代码
希望这能有所帮助。