序文以前、ある会社の面接に行ったとき、面接官から「オブジェクトを深くコピーするにはどうすればよいですか?」という質問を受けました。その時、私は密かに嬉しく思いました。こんな単純な疑問を考える必要があるのでしょうか?そこで私はこう言いました。「よく使われる方法は 2 つあります。1 つ目は JSON.parse(JSON.stringify(obj)) を使用する方法で、2 つ目は for...in と再帰を使用する方法です。」これを聞いた面接官はうなずき、満足そうでした。 質問するでは、上で述べたバグとは何でしょうか? 特殊オブジェクトのコピー まず、共通の型を考慮せずに、次のメンバーを持つオブジェクトを想像してみましょう。 定数オブジェクト = { 編曲: [111, 222], obj: {キー: 'オブジェクト'}, a: () => {console.log('function')}, 日付: 新しい Date(), 登録: /regular/ig } 次に、上記の2つの方法をそれぞれ使用してコピーします。 JSON メソッド JSON.parse(JSON.stringify(obj)) 出力: obj 内の通常のオブジェクトと配列の両方をコピーできることがわかりますが、日付オブジェクトは文字列になり、関数は直接消え、正規表現は空のオブジェクトになります。 再帰 関数isObj(obj) { 戻り値 (typeof obj === 'オブジェクト' || typeof obj === '関数') && obj !== null } 関数 deepCopy(obj) { tempObj = Array.isArray(obj) ? [] : {} とします。 for(let key in obj) { tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key] } tempObjを返す } 結果: 結論は 上記のテストから、これら 2 つのメソッドは function、date、reg タイプのオブジェクトをコピーできないことがわかります。
リングとは何ですか? ループはオブジェクト間の循環参照であり、閉じたループになります。たとえば、次のオブジェクトがあります。 var a = {} aa = ア 上記の2つの方法でコピーすると、エラーが直接報告されます。 解決
コピーされたオブジェクトを格納するために WeakMap 構造体を使用することができます。オブジェクトをコピーするたびに、WeakMap を照会して、オブジェクトがコピーされたかどうかを確認します。コピーされた場合は、オブジェクトを取り出して返します。deepCopy 関数を次のように変換します。 関数 deepCopy(obj, hash = new WeakMap()) { hash.has(obj) の場合、hash.get(obj) を返します。 cloneObj = Array.isArray(obj) ? [] : {} とします。 ハッシュを設定します(obj、クローンObj) for (let key in obj) { cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key]; } cloneObjを返す } リング結果をコピー: 特殊オブジェクトのコピー この問題の解決法は、特別に扱う必要があるオブジェクトの種類が多すぎるため、かなり複雑です。そこで、MDN の構造化コピーを参照し、それをリングの解決法と組み合わせました。 // 日付と登録型のみを解決し、他の型は自分で追加できます。 function deepCopy(obj, hash = new WeakMap()) { cloneObj を作ろう コンストラクタ = obj.constructor switch(コンストラクタ){ ケース正規表現: cloneObj = 新しいコンストラクタ(obj) 壊す 事件日: cloneObj = 新しいコンストラクタ(obj.getTime()) 壊す デフォルト: hash.has(obj) の場合、hash.get(obj) を返します。 cloneObj = 新しいコンストラクタ() ハッシュを設定します(obj、クローンObj) } for (let key in obj) { cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key]; } cloneObjを返す } コピー結果: 完全版については、lodash deep copyをご覧ください。
ただし、MDN の構造化コピーでは、関数のコピーの問題は依然として解決されません。 これまでは関数をコピーするために eval メソッドを使うことしか考えていませんでしたが、この方法はアロー関数にしか機能しません。fun(){} の形式だと失敗します。 関数をコピーして関数タイプを追加する 結果をコピー エラーの種類 追記JavaScript のディープ コピーには、上記で説明した問題以外にも多くの問題があります。もう 1 つの問題は、プロトタイプ チェーン上のプロパティをどのようにコピーするかということです。列挙不可能なプロパティをコピーする方法、エラー オブジェクトをコピーする方法などについては、ここでは詳しく説明しません。 ただし、日常生活では依然として JSON メソッドを使用することをお勧めします。このメソッドはほとんどのビジネス ニーズをカバーしているため、単純なことを複雑にする必要はありません。ただし、面接中に細かいことを気にする面接官に遭遇した場合、この質問に対する答えは間違いなく面接官の印象を良くするでしょう。 これで、JavaScript ディープ コピーの落とし穴に関するこの記事は終了です。JavaScript ディープ コピーに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: alpineをベースにdockerfileで作成したクローラーScrapyイメージの実装
>>: mysql mycat ミドルウェアのインストールと使用
<br />前回は、Web テーブルにセルの線を設定する方法を学びました。今日は、Web...
ウェブサイト管理者は、さまざまな理由や操作により、ウェブサイトのデータを誤って削除したり、ウェブサイ...
この読書ノートでは、主にファイルシステムに関連する操作を記録します。ディスクとディレクトリの容量ディ...
コンテンツ属性は通常、::before および ::after 疑似要素で使用され、疑似要素のコンテ...
目次1. はじめに2. タブバーのスタイルをカスタマイズする3. カスタムタブバーと関連設定を導入す...
1. mycatとはエンタープライズアプリケーション開発のための完全にオープンソースの大規模データベ...
目次デコレータパターンの紹介TypeScript のデコレータデコレータの使用デコレーターファクトリ...
マウスをホバーすると画像が折りたたまれる効果を実現する CSS 1. 実施のポイント折り畳みは複数の...
メインライブラリの構成1. MySQLを設定する vim /etc/my.cn # ファイルに次の内...
この記事では、VMware Toolsのインストールと構成に関するグラフィックチュートリアルを参考と...
今日もまた罠に落ちてしまいました。 私は以前MySQLの主キーオーバーフローに遭遇したことがあり、そ...
1. MySQL rpm パッケージのインストール # インストールソースをダウンロードします [r...
CentOS 7にPostgreSQL 11をインストールする PostgreSQL: 世界で最も先...
Docker 学習https://www.cnblogs.com/poloyy/p/15257059...
アプリケーションが牛のように遅い理由は数多くあります。ネットワーク、システム アーキテクチャ、または...