假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
假设我有一个选项变量我想设置一个默认值。
这两种选择的优点/缺点是什么?
使用对象扩展
options = {...optionsDefault, ...options};
或者使用Object.assign
options = Object.assign({}, optionsDefault, options);
这是让我疑惑的承诺。
当前回答
作为参考,对象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}
其他回答
我想总结一下“扩展对象合并”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的意图。但多年后,理查德(在我看来)证明是对的。所以我写了这个答案,希望它最终能取代旧的答案(可能需要几年时间,但毕竟这就是长尾效应的意义所在)。
作为参考,对象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}
这并不一定详尽无遗。
传播的语法
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捆绑),这就是我所说的:你可以编译的语法。他们显然更喜欢这样,而不是必须将对象赋值作为一个依赖项包含到他们的构建中。
(1)创建对象的浅副本和(2)将多个对象合并为单个对象的方法在2014年至2018年之间有了很大的发展。
下面概述的方法在不同时期变得可用并广泛使用。这个答案提供了一些历史视角,但并不详尽。
如果没有库或现代语法的帮助,您将使用for-in循环,例如。 var mergedOptions = {} for (var键在defaultOptions) { mergedOptions[key] = defaultOptions[key] } 对于(var键在选项中){ mergedOptions[key] = options[key] } options = mergedOptions
2006
jQuery 1.0有jQuery.extend(): 选项= $。extend({}, defaultOptions, options)
⋮
2010
下划线。js 1.0有_.extend() 选项= _。extend({}, defaultOptions, options)
⋮
2014
2ality发布了一篇关于Object.assign()加入ES2015的文章 对象分配发布到npm。 var objectAssign = require('object-assign') options = objectAssign({}, defaultOptions, options) ES2016提出的对象Rest/扩展属性语法。
2015
对象。Chrome (45), Firefox(34)和Node.js(4)都支持assign。不过,旧的运行时需要Polyfill。 options =对象。assign({}, defaultOptions, options) 对象Rest/Spread Properties提案进入第二阶段。
2016
对象Rest/扩展属性语法没有被包含在ES2016中,但是提案已经到了第三阶段。
2017
对象Rest/Spread属性语法没有包含在ES2017中,但在Chrome (60), Firefox(55)和Node.js(8.3)中可用。不过,旧的运行时需要一些编译。 选项={…defaultOptions,…选择}
2018
对象Rest/Spread Properties提案达到了第4阶段,语法被包含在ES2018标准中。
对象。当目标对象是一个常量并且您希望一次设置多个属性时,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。