AnglarのObject.assign
22597 ワード
ES 2015のいくつかの新しい内容は、Object.assign関数の使用によって、一つ以上のオブジェクトを対象オブジェクトに素早くコピーすることができます.本文の内容はes 6、s 7関連のオブジェクトの複製の内容と、いくつかのess 5の代替案の紹介に関連します.
関数プロトタイプ
まず関数の定義を参照してください.関数パラメータは最終的な戻り値として対象となり、ソースオブジェクト(ここでは任意の複数)です.この関数を呼び出すことにより、列挙可能な自己属性値をすべて対象オブジェクトにコピーすることができます.
列挙可能な属性自己属性stringまたはSymbolタイプは直接に割り当てられるです.
コピープロセスでは、ソースオブジェクトのgetterメソッドを呼び出し、ターゲットオブジェクトのコピーをtargetオブジェクト上でsetter法を用いて実現する.
関数の例
ここではいくつかのMDN上の例を通して、使い方を紹介します.
実例の一
上記のプロトタイプ関数を参照して説明すれば、最初のo 1はタージに設定されているので、そのsetterメソッドを呼び出して他のオブジェクトの属性を自身に設定します.
いくつかのオブジェクトをカスタマイズしましたが、これらのオブジェクトには列挙できない属性が含まれています.またObject.definePropertyを使って初期化するオブジェクトはデフォルトでは列挙できない属性です.列挙できる対象については、Object.keys()を直接使用して獲得したり、for-i nを使って巡回してみたりできます.
列挙できない属性については、Object.assignを使用すると自動的に無視されます.
読み取り専用の属性については、新しいオブジェクトを割り当てて上書きすると、例外を投げます.
ここでは簡単に、どうやってes 5バージョンのObject.assignを実現するかを見ます.
実装ステップ:
オリジナルがこの関数をサポートしているかどうかを判断します.存在しない場合は即実行関数を作成します.この関数はassign関数を作成してObjectに結合します.パラメータが正しいかどうかを判断します.目的のオブジェクトは空ではなく、直接に「-」を設定して送ることができます.ただし、この値を設定してください.Objectを使用して元のオブジェクトに戻し、out として保存します.
for...inサイクルを使って、すべてのエニュメレーションオブジェクトを巡回します.新しいオブジェクトにコピーします.ソースは以下の通りです
1.深さコピー
私たちは次の関数を呼び出すと、Object.assignは前の内容を上書きしますので、完全にオブジェクトを融合させることはできません.全部置換しますので、戻ってきたオブジェクトの内容は最後の値になります.
{a:{b:1,c:3}
このように私たちは自分のアルゴリズムを実現して深層コピーを完成しなければなりませんが、githubには既に多くの良い解決策があります.
2.ES 2016実現
es 7において、私たちは、rest属性を使用して、残りのオブジェクトのすべてを捕獲することができます.例えば、以下の例(babel-replページテストを使用してもいいです.ブラウザはまだサポートされていません.)
関数プロトタイプ
まず関数の定義を参照してください.関数パラメータは最終的な戻り値として対象となり、ソースオブジェクト(ここでは任意の複数)です.この関数を呼び出すことにより、列挙可能な自己属性値をすべて対象オブジェクトにコピーすることができます.
Object.assign(target,...sources)
ここで強調したい3つの点は、列挙可能な属性自己属性stringまたはSymbolタイプは直接に割り当てられるです.
コピープロセスでは、ソースオブジェクトのgetterメソッドを呼び出し、ターゲットオブジェクトのコピーをtargetオブジェクト上でsetter法を用いて実現する.
関数の例
ここではいくつかのMDN上の例を通して、使い方を紹介します.
実例の一
上記のプロトタイプ関数を参照して説明すれば、最初のo 1はタージに設定されているので、そのsetterメソッドを呼び出して他のオブジェクトの属性を自身に設定します.
var o1 ={ a:1};var o2 ={ b:2};var o3 ={ c:3};var obj =Object.assign(o1, o2, o3);
console.log(obj);// { a: 1, b: 2, c: 3 }
console.log(o1);// { a: 1, b: 2, c: 3 }, target object itself is changed.
実例2いくつかのオブジェクトをカスタマイズしましたが、これらのオブジェクトには列挙できない属性が含まれています.またObject.definePropertyを使って初期化するオブジェクトはデフォルトでは列挙できない属性です.列挙できる対象については、Object.keys()を直接使用して獲得したり、for-i nを使って巡回してみたりできます.
列挙できない属性については、Object.assignを使用すると自動的に無視されます.
var obj =Object.create({ foo:1},{// foo is an inherit property.
bar:{
value:2// bar is a non-enumerable property.},
baz:{
value:3,
enumerable:true// baz is an own enumerable property.}});var copy =Object.assign({}, obj);
console.log(copy);// { baz: 3 }
実例3読み取り専用の属性については、新しいオブジェクトを割り当てて上書きすると、例外を投げます.
var target =Object.defineProperty({},'foo',{
value:1,
writable:false});Object.assign(target,{ bar:2})//{bar: 2, foo: 1}Object.assign(target,{ foo:2})//Uncaught TypeError: Cannot assign to read only property 'foo' of object '#
Polyfillここでは簡単に、どうやってes 5バージョンのObject.assignを実現するかを見ます.
実装ステップ:
オリジナルがこの関数をサポートしているかどうかを判断します.存在しない場合は即実行関数を作成します.この関数はassign関数を作成してObjectに結合します.パラメータが正しいかどうかを判断します.目的のオブジェクトは空ではなく、直接に「-」を設定して送ることができます.ただし、この値を設定してください.Objectを使用して元のオブジェクトに戻し、out として保存します.
for...inサイクルを使って、すべてのエニュメレーションオブジェクトを巡回します.新しいオブジェクトにコピーします.ソースは以下の通りです
if(typeofObject.assign !='function'){(function(){Object.assign =function(target){'use strict';if(target ===undefined|| target ===null){thrownewTypeError('Cannot convert undefined or null to object');}var output =Object(target);for(var index =1; index < arguments.length; index++){var source = arguments[index];if(source !==undefined&& source !==null){for(var nextKey in source){if(source.hasOwnProperty(nextKey)){
output[nextKey]= source[nextKey];}}}}return output;};})();}
拡張内容1.深さコピー
私たちは次の関数を呼び出すと、Object.assignは前の内容を上書きしますので、完全にオブジェクトを融合させることはできません.全部置換しますので、戻ってきたオブジェクトの内容は最後の値になります.
{a: {c: 3}
Object.assign({a:{b:0}},{a:{b:1, c:2}},{a:{c:3}});
どのように深層的に融合するか、例えば私達が期待する出力結果は以下の通りです.{a:{b:1,c:3}
このように私たちは自分のアルゴリズムを実現して深層コピーを完成しなければなりませんが、githubには既に多くの良い解決策があります.
2.ES 2016実現
es 7において、私たちは、rest属性を使用して、残りのオブジェクトのすべてを捕獲することができます.例えば、以下の例(babel-replページテストを使用してもいいです.ブラウザはまだサポートされていません.)
let { fname, lname,...rest }={ fname:"Hemanth", lname:"HM", location:"Earth", type:"Human"};
fname;//"Hemanth"
lname;//"HM"
rest;// {location: "Earth", type: "Human"}
このようにして、私たちはこの特性を使って、assign関数を実現することができます.let oldObj1={a:"a",b:{b1:"b1"}}
let oldObj2={a:"a1",b:{b2:"b2"},c:"c"}
let newObject={...oldObj1,...oldObj2};
console.log(newObject){"a":"a1","b":{"b2":"b2"},"c":"c"}
しかし依然として浅い層の交替だけで、深い層の合併を実現していません.