對象傳播與Object.assign

本文翻譯自:Object spread vs. Object.assign

Let's say I have an options variable and I want to set some default value. 假設我有一個options變量,並且想要設置一些默認值。

What's is the benefit / drawback of these two alternatives? 這兩種選擇的優點/缺點是什麼?

Using object spread 使用對象傳播

options = {...optionsDefault, ...options};

Or using Object.assign 或使用Object.assign

options = Object.assign({}, optionsDefault, options);

This is the commit that made me wonder. 這就是讓我感到奇怪的承諾


#1樓

參考:https://stackoom.com/question/2E9Po/對象傳播與Object-assign


#2樓

This isn't necessarily exhaustive. 這並不一定是詳盡無遺的。

Spread syntax 傳播語法

options = {...optionsDefault, ...options};

Advantages: 好處:

  • If authoring code for execution in environments without native support, you may be able to just compile this syntax (as opposed to using a polyfill). 如果編寫代碼以在沒有本機支持的環境中執行,則可以僅編譯此語法(與使用polyfill相對)。 (With Babel, for example.) (例如,使用Babel。)

  • Less verbose. 不太冗長。

Disadvantages: 缺點:

  • When this answer was originally written, this was a proposal , not standardized. 最初編寫此答案時,這只是一個建議 ,而不是標準化的。 When using proposals consider what you'd do if you write code with it now and it doesn't get standardized or changes as it moves toward standardization. 使用投標時,請考慮一下如果現在用它編寫代碼會做什麼,並且在朝着標準化的方向發展時,它不會變得標準化或更改。 This has since been standardized in ES2018. 此後已在ES2018中標準化。

  • Literal, not dynamic. 從字面上看,不是動態的。


Object.assign()

options = Object.assign({}, optionsDefault, options);

Advantages: 好處:

  • Standardized. 標準化。

  • Dynamic. 動態。 Example: 例:

     var sources = [{a: "A"}, {b: "B"}, {c: "C"}]; options = Object.assign.apply(Object, [{}].concat(sources)); // or options = Object.assign({}, ...sources); 

Disadvantages: 缺點:

  • More verbose. 更詳細。
  • If authoring code for execution in environments without native support you need to polyfill. 如果編寫代碼以在沒有本機支持的環境中執行,則需要polyfill。

This is the commit that made me wonder. 這就是讓我感到奇怪的承諾。

That's not directly related to what you're asking. 這與您的要求沒有直接關係。 That code wasn't using Object.assign() , it was using user code ( object-assign ) that does the same thing. 該代碼未使用Object.assign() ,而是在執行相同功能的用戶代碼( object-assign )中使用。 They appear to be compiling that code with Babel (and bundling it with Webpack), which is what I was talking about: the syntax you can just compile. 他們似乎正在使用Babel編譯該代碼(並將其與Webpack捆綁在一起),這就是我所說的:您可以編譯的語法。 They apparently preferred that to having to include object-assign as a dependency that would go into their build. 他們顯然更喜歡必須將object-assign作爲依賴項納入其構建中。


#3樓

The object spread operator (...) doesn't work in browsers, because it isn't part of any ES specification yet, just a proposal. 對象散佈運算符(...)在瀏覽器中不起作用,因爲它還不是任何ES規範的一部分,只是一個建議。 The only option is to compile it with Babel (or something similar). 唯一的選擇是用Babel(或類似的東西)編譯它。

As you can see, it's just syntactic sugar over Object.assign({}). 如您所見,它只是Object.assign({})上的語法糖。

As far as I can see, these are the important differences. 據我所知,這些是重要的區別。

  • Object.assign works in most browsers (without compiling) Object.assign在大多數瀏覽器中均可運行(無需編譯)
  • ... for objects isn't standardized ...對於對象未標準化
  • ... protects you from accidentally mutating the object ...保護您免於意外改變對象
  • ... will polyfill Object.assign in browsers without it ...將在沒有它的情況下在瀏覽器中填充Object.assign
  • ... needs less code to express the same idea ...需要更少的代碼來表達相同的想法

#4樓

This is now part of ES6, thus is standardized, and is also documented on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator 現在,它已成爲ES6的一部分,因此已經標準化,並且還記錄在MDN上: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

It's very convenient to use and makes a lot of sense alongside object destructuring. 它非常方便使用,並且與對象分解一起意義重大。

The one remaining advantage listed above is the dynamic capabilities of Object.assign(), however this is as easy as spreading the array inside of a literal object. 上面列出的一個剩餘優點是Object.assign()的動態功能,但是,這與將數組擴展到文字對象內部一樣容易。 In the compiled babel output it uses exactly what is demonstrated with Object.assign() 在編譯的babel輸出中,它完全使用Object.assign()演示的內容

So the correct answer would be to use object spread since it is now standardized, widely used (see react, redux, etc), is easy to use, and has all the features of Object.assign() 因此正確的答案是使用對象散佈,因爲它已經標準化,被廣泛使用(請參閱react,redux等),易於使用並且具有Object.assign()的所有功能


#5樓

As others have mentioned, at this moment of writing, Object.assign() requires a polyfill and object spread ... requires some transpiling (and perhaps a polyfill too) in order to work. 正如其他人提到的那樣,在撰寫本文時, Object.assign()需要一個polyfill和對象散佈...需要一些轉譯(也許還有一個polyfill)才能工作。

Consider this code: 考慮以下代碼:

// 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);

These both produce the same output. 這些都產生相同的輸出。

Here is the output from Babel, to ES5: 這是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);

This is my understanding so far. 到目前爲止,這是我的理解。 Object.assign() is actually standardised, where as object spread ... is not yet. 實際上Object.assign()是標準化的,因爲對象散佈還沒有... The only problem is browser support for the former and in future, the latter too. 唯一的問題是瀏覽器支持前者,將來也支持後者。

Play with the code here 在這裏玩代碼

Hope this helps. 希望這可以幫助。


#6樓

For reference object rest/spread is finalised in ECMAScript 2018 as a stage 4. The proposal can be found here . 作爲參考,對象的休息/傳播在ECMAScript 2018中最終確定爲階段4。可以在此處找到建議。

For the most part object reset and spread work the same way, the key difference is that spread defines properties, whilst Object.assign() sets them . 大多數情況下,對象重置和散佈都以相同的方式進行,主要區別在於散佈定義屬性,而Object.assign()設置屬性 This means Object.assign() triggers setters. 這意味着Object.assign()觸發設置器。

It's worth remembering that other than this, object rest/spread 1:1 maps to Object.assign() and acts differently to array (iterable) spread. 值得記住的是,除此之外,對象休息/傳播1:1映射到Object.assign()並以不同的方式作用於數組(可迭代)傳播。 For example, when spreading an array null values are spread. 例如,在擴展數組時,將擴展空值。 However using object spread null values are silently spread to nothing. 但是,使用對象擴展時,空值會默默地擴展爲零。

Array (Iterable) Spread Example 數組(可迭代)傳播示例

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

Object Spread Example 對象傳播示例

const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};

console.log(z); //{a: 1, b: 2}

This is consistent with how Object.assign() would work, both silently exclude the null value with no error. 這與Object.assign()的工作方式一致,兩者都無提示地無提示地排除了null值。

const x = null;
const y = {a: 1, b: 2};
const z = Object.assign({}, x, y);

console.log(z); //{a: 1, b: 2}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章