options
変数があり、デフォルト値を設定したいとしましょう。
これら2つの選択肢の利点/欠点は何ですか?
オブジェクトスプレッドを使用する
options = {...optionsDefault, ...options};
またはObject.assignを使用する
options = Object.assign({}, optionsDefault, options);
これが commit です。
これは必ずしも徹底的ではありません。
options = {...optionsDefault, ...options};
ネイティブサポートのない環境で実行するためのコードをオーサリングする場合は、(polyfillを使用するのではなく)この構文をコンパイルすることしかできないかもしれません。 (たとえば、Babelと)
あまり冗長ではありません。
この答えが最初に書かれたとき、これは 提案 であり、標準化されていませんでした。プロポーザルを使用するときは、今それを使ってコードを作成し、標準化されなかったり、標準化に向かって変化したりした場合に何をするべきかを検討してください。これはES2018で標準化されました。
文字通り、動的ではありません。
Object.assign()
options = Object.assign({}, optionsDefault, options);
標準化されました。
動的。例:
var sources = [{a: "A"}, {b: "B"}, {c: "C"}];
options = Object.assign.apply(Object, [{}].concat(sources));
// or
options = Object.assign({}, ...sources);
これが私を驚かせたコミットメントです。
それは直接あなたが求めていることとは関係ありません。そのコードはObject.assign()
を使用していませんでした、それは同じことをするユーザーコード(object-assign
)を使用していました。彼らはそのコードをBabelでコンパイルして(そしてWebpackにバンドルして)いるように見えます。それが私が話していたものです:あなたがただコンパイルできる構文です。彼らは明らかに彼らのビルドに入るだろう依存関係としてobject-assign
を含まなければならないことを好みました。
参照対象については、休息/スプレッドは段階4としてECMAScript 2018で最終決定される - 提案は ここで 見つけられることができる。
ほとんどの場合、オブジェクトのリセットと拡散は同じように機能しますが、主な違いは spreadはプロパティを定義し、Object.assign()はプロパティを設定します これは、Object.assign()が設定メソッドを起動することを意味します。
これ以外にも、object rest/spread 1:1はObject.assign()にマップされ、array(iterable)spreadとは異なる動作をすることを覚えておく価値があります。たとえば、配列を拡散するとき、null値が拡散されます。ただし、オブジェクトスプレッドを使用すると、null値は何もしないで静かに広げられます。
配列(反復可能)スプレッドの例
const x = [1, 2, null , 3];
const y = [...x, 4, 5];
console.log(y); // [1, 2, null, 3, 4, 5];
オブジェクトスプレッドの例
const x = null;
const y = {a: 1, b: 2};
const z = {...x, ...y};
console.log(z); //{a: 1, b: 2}
これは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}
スプレッド演算子とObject.assign
の間の大きな違いの1つは、現在の答えでは言及されていないようですが、スプレッド演算子がプロトタイプを損なわないことです。オブジェクトにプロパティを追加したいが、それがインスタンスであるものを変更したくないのであれば、Object.assign
を使う必要があります。以下の例はこれを実証するはずです。
const error = new Error();
console.error instanceof Error; // true
const errorExtendedUsingSpread = {
...error,
...{
someValue: true
}
};
errorExtendedUsingSpread instanceof Error; // false
const errorExtendedUsingAssign = Object.assign(error, {
someValue: true
});
errorExtendedUsingAssign instanceof Error; // true
オブジェクトスプレッド演算子(...)はブラウザでは機能しません。これはまだES仕様の一部ではないため、単なる提案です。唯一の選択肢は、それをBabel(または同様のもの)でコンパイルすることです。
ご覧のとおり、それはObject.assign({})に対する単なる構文上の糖です。
私が見ることができる限りでは、これらは重要な違いです。
...
は標準化されていません...
は、誤ってオブジェクトを変更してしまうことからあなたを保護します...
はそれなしでブラウザでObject.assignをpolyfillします...
は同じ考えを表現するのに必要なコードが少なくてすみます他の人が言っているように、この文書を書いている時点では、Object.assign()
はpolyfillを必要とし、オブジェクトスプレッド...
は動作するためにある程度のtranspiling(そしておそらくpolyfillも)を必要とします。
このコードを考えてください:
// 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()
は実際には標準化されていますが、オブジェクトスプレッドとしての...
はまだ未定です。唯一の問題は前者と将来のブラウザサポートです。
お役に立てれば。
私は、「スプレッドオブジェクトマージ」ES機能の状況をブラウザで、そしてツールを介してエコシステムで要約したいと思います。
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以降)では変換なしで動作します。
私は最初の質問の後にこの2.5 years を書いています。しかし、私は全く同じ質問をしていました、そしてこれはGoogleが私に送ったところです。私はロングテールを改善するというSOの任務の奴隷です。
これは「配列拡張」構文の拡張であるため、Googleで検索することは非常に困難であり、互換性テーブルで見つけることは困難です。私が見つけることができる最も近いのは Kangax "property spread" ですが、そのテストは同じ式に2つのスプレッドを持っていません(マージではありません)。また、提案/下書き/ブラウザステータスページの名前はすべて "プロパティスプレッド"を使用していますが、それはコミュニティが "オブジェクトマージ"のスプレッド構文を使用する提案の後に到達した "最初のプリンシパル"だったようです。そこで、私は自分の発見をここに文書化して、この特定の機能に関するリンクを他の人が閲覧、更新、およびコンパイルできるようにします。それがキャッチされることを願っています。それが着陸したというニュースをスペックとブラウザに広めるのを手伝ってください。
最後に、この情報をコメントとして追加したはずですが、著者の当初の意図を損なわずにそれらを編集することはできませんでした。具体的には、@ ChicPenguinのコメントを編集して、@ RichardSchulteを修正するという意図を失うことはできません。しかし数年後、リチャードは(私の意見では)正しいことがわかりました。それで、私は代わりにこの答えを書きます、それが結局古い答えで牽引力を得ることを望んでいます(何年もかかるかもしれませんが、結局それがlong tail効果についてのすべてであるものです)。
注:SpreadはObject.assignを囲む単なる構文上の糖ではありません。それらは舞台裏ではかなり異なった働きをします。
Object.assignはセッターを新しいオブジェクトに適用しますが、Spreadは適用しません。さらに、オブジェクトは反復可能でなければなりません。
コピー 現時点でオブジェクトの値が必要で、その値にそのオブジェクトの他の所有者による変更が反映されないようにするには、これを使用します。
オブジェクトのシャローコピーを作成するためにこれを使用して、常にimmutableプロパティをcopyに設定します - 可変バージョンはimmutableプロパティに渡すことができるので、copyは常にimmutableオブジェクトを扱うようにします
割り当て 割り当てはコピーとは反対です。代入は、値をコピーまたは保持するのではなく、インスタンス変数に直接代入するセッターを生成します。割り当てプロパティの取得メソッドを呼び出すと、実際のデータへの参照が返されます。
他の答えは古く、良い答えを得ることができませんでした。
以下の例はオブジェクトリテラルのためのもので、両者がどのようにして互いに補完することができ、またどのようにして互いを補完することができないか(したがって違い)を助けます。
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
これは現在ES6の一部であり、したがって標準化されており、MDNでも文書化されています。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
それは使用するのが非常に便利で、オブジェクトの破壊と並んでとても意味があります。
上に挙げたもう1つの利点は、Object.assign()の動的な機能ですが、これは配列をリテラルオブジェクト内に展開するのと同じくらい簡単です。コンパイルされたbabelの出力では、Object.assign()で示されたものをそのまま使用しています。
そのため、正解は、標準化され、広く使用されているので(react、reduxなどを参照)、使いやすく、Object.assign()のすべての機能を備えているので、object spreadを使用することです。