JavaScript Deep Copyは初心者や経験豊富なものによって開発されており、多くの場合問題に遭遇し、JavaScriptのディープコピーを非常によく理解することはできません。
deepclone?
ディープコピーの反対は浅いコピーです。多くの初心者は、この気持ちに接触すると混乱しています。
なぜディープコピーを使用するのですか?
多くの場合、変数に値を割り当て、メモリアドレスに値を割り当てる必要があります。ただし、参照値タイプを割り当てる場合、メモリ領域のみを共有するため、割り当て時に以前の値と一貫性を維持します。
特定の例を参照してください
// var test = {a: 'a'、b: 'b'}; // test2にtest2に割り当てることにvar test = {a: 'a'、b: 'b'}を割り当てるには、テストとtest2が同じメモリオブジェクトを共有します。図:
これは、参照値タイプのデータが互いに影響する理由を理解することをお勧めします。
成し遂げる
ディープコピー関数を実装するには、JavaScriptの数値タイプについて話す必要があります。
JavaScriptタイプを決定します
JavaScriptには次の基本的なタイプがあります
タイプ説明
未定義の型型の型には、1つの値が定義されていない値が1つしかありません。これは、変数が割り当てられていない場合の値です。
nullnullタイプには1つの値nullのみがあり、それは空のオブジェクトの参照です
booleanbooleanには2つの値があります:trueとfalse
文字列それはテキスト情報を表します
番号デジタル情報を表します
オブジェクト関数と配列配列など、一連のプロパティの順序付けられていないコレクションです
TypeOFを使用して機能と配列を判断することは不可能です。ここでは、object.prototype.tostringメソッドを使用します。
[デフォルトでは、各オブジェクトはオブジェクトからtoString()メソッドに継承します。このメソッドがオブジェクト自体の同じ名前メソッドまたはより近い上部プロトタイプで上書き(ブロック)されない場合、オブジェクトのtoString()メソッドが呼び出され、ここで文字列タイプはオブジェクトタイプを表します[1]
関数型(obj){var toString = object.prototype.toString; var map = {'[object boolean]': 'boolean'、 '[object number]': 'number'、 '[object string]:' string '、' [object array] ':' function '、' [object array]: 'array'、 '[array]、' [object regexp]: 'objexp' '' '' 'objexp' '' '' 'define 'null'、 '[object object]': 'object'}; RETURN MAP [toString.call(obj)];}DeepCloneを実装します
非参照値タイプの数値の場合、値は直接割り当てられ、参照される値タイプ(オブジェクト)の場合、再びトラバースして再帰的に割り当てる必要があります。
function deepclone(data){var t = type(data)、o、i、ni; if(t === 'array'){o = []; } else if(t === 'object'){o = {}; } else {return data; } if(t === 'array'){for(i = 0、ni = data.length; i <ni; i ++){o.push(deepclone(data [i])); } return o; } else if(t === 'object'){for(i in data){o [i] = deepclone(data [i]); } return o; }}ここには、誰もが注意を払うべきであるという点があります。関数タイプの場合、ブロガーは値を直接割り当てたり、メモリ値を共有したりしますか。これは、関数が特定の機能を完了し、入力値と返品値を備えたものであり、上位レベルのサービスの場合、ビジネス機能の完了に関するものであり、関数を深くコピーする必要はないためです。
しかし、関数タイプをコピーする方法は?
実際、ブロガーはそれを操作するためにNewを使用することだけを考えましたが、機能は一度実行されます。 o(□)o!まだ良いアイデアはありません。ガイダンスをください!
この時点で、ディープコピーはほぼ完成しましたが、一部の人々は、なぜ浅いコピーが実装されなかったと考えていますか?
浅いコピー?
浅いコピーの場合、1つの一般的なメモリ領域のみを動作させると理解できます!ここには危険があります! (..*)
この共有データを制御せずに直接操作すると、データの例外がしばしば発生し、他の部分によって変更されます。したがって、データソースを直接操作しないでください。いくつかの方法をカプセル化して、データ上でカード操作を実行します。
おそらくここではほぼ同じですが、フロントエンドとして、JavaScript自体だけでなく、DOM、ブラウザなども考慮しています。
要素タイプ
次のコードを見てみましょう。結果に何が返されますか?
Object.prototype.toString.call(document.getElementsByTagName('div')[0])
答えは[オブジェクトhtmldivelement]です
DOM要素が保存され、誤って深くコピーすると、上記の深いコピー関数には要素要素に関する判断がありません。要素要素を判断するには、Instanceofを使用して判断します。なぜなら、異なるタグの場合、ToStringは異なるタグに対応するコンストラクターを返します。
関数型(obj){var toString = object.prototype.toString; var map = {'[object boolean]': 'boolean'、 '[object number]': 'number'、 '[object string]:' string '、' [object array] ':' function '、' [object array]: 'array'、 '[array]、' [object regexp]: 'objexp' '' '' 'objexp' '' '' 'define 'null'、 '[object object]': 'object'}; if(obj instanceof element){return 'element'; } return map [toString.call(obj)];}他の方法?
jQueryの実装
詳細については、https://github.com/jquery/jquを参照してください。
実装を強調します
詳細については、https://github.com/jashkenas/...を参照してください。
Lodashの実装
詳細については、https://github.com/lodash/lodを参照してください。
JSON実装
最初にjson.stringifyを通過し、次にjson.parseを通過することで、深いコピーを実現できます。ただし、データ型は基本的な数値タイプのみをサポートしています。
var obj = {a: 'a'、b:function(){console.log( 'b')}} // json.stringifyの場合、関数はフィルタリングされます。 json.stringify(obj)// "{" a ":" a "}"まとめ
ここでは、ディープコピーとディープコピーの実装方法を大まかに要約します。さまざまなシナリオで、ビジネスシナリオに基づいてディープコピーが必要かどうかを判断する必要があります。