JavaScript 中对象的深拷贝
在JavaScript中,对对象进行拷贝的场景比较常见。但是简单的复制语句只能对对象进行浅拷贝,即复制的是一份引用,而不是它所引用的对象。而更多的时候,我们希望对对象进行深拷贝,避免原始对象被无意修改。
对象的深拷贝与浅拷贝的区别如下:
浅拷贝:仅仅复制对象的引用,而不是对象本身;
深拷贝:把复制的对象所引用的全部对象都复制一遍。
一. 浅拷贝的实现
浅拷贝的实现方法比较简单,只要使用是简单的复制语句即可。
1.1 方法一:简单的复制语句
/* ================ 浅拷贝 ================ */ function simpleClone(initalObj) { var obj = {}; for ( var i in initalObj) { obj[i] = initalObj[i]; } return obj; }
/* ================ 客户端调用 ================ */ var obj = { a: "hello", b: { a: "world", b: 21 }, c: ["Bob", "Tom", "Jenny"], d: function() { alert("hello world"); } } var cloneObj = simpleClone(obj); // 对象拷贝 console.log(cloneObj.b); // {a: "world", b: 21} console.log(cloneObj.c); // ["Bob", "Tom", "Jenny"] console.log(cloneObj.d); // function() { alert("hello world"); } // 修改拷贝后的对象 cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b); // {a: "changed", b: 21} // // 原对象所引用的对象被修改了 console.log(obj.c); // ["Bob", "Tom", "Jenny"] // 原对象所引用的对象未被修改 console.log(obj.d); // function() { alert("hello world"); } // 原对象所引用的函数未被修改
1.2 方法二:Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
二. 深拷贝的实现
要实现深拷贝有很多办法,有最简单的 JSON.parse() 方法,也有常用的递归拷贝方法,和ES5中的 Object.create() 方法。
2.1 方法一:使用 JSON.parse() 方法
要实现深拷贝有很多办法,比如最简单的办法是使用 JSON.parse():
/* ================ 深拷贝 ================ */ function deepClone(initalObj) { var obj = {}; try { obj = JSON.parse(JSON.stringify(initalObj)); } return obj; }
/* ================ 客户端调用 ================ */ var obj = { a: { a: "world", b: 21 } } var cloneObj = deepClone(obj); cloneObj.a.a = "changed"; console.log(obj.a.a); // "world"
这种方法简单易用。
但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。
2.2 方法二:递归拷贝
代码如下:
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { if (typeof initalObj[i] === 'object') { obj[i] = (initalObj[i].constructor === Array) ? [] : {}; arguments.callee(initalObj[i], obj[i]); } else { obj[i] = initalObj[i]; } } return obj; }
上述代码确实可以实现深拷贝。但是当遇到两个互相引用的对象,会出现死循环的情况。
为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。
改进版代码如下:
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; arguments.callee(prop, obj[i]); } else { obj[i] = prop; } } return obj; }
2.3 方法三:使用Object.create()方法
直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; }
三. 参考:jQuery.extend()方法的实现
jQuery.js的jQuery.extend()也实现了对象的深拷贝。下面将官方代码贴出来,以供参考。
官方链接地址:http://www.php.cn/。
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = jQuery.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray( src ) ? src : []; } else { clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };
以上就是JavaScript 中对象的深拷贝的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



JSON (JavaScriptObjectNotation) ialah format pertukaran data ringan yang telah menjadi format biasa untuk pertukaran data antara aplikasi web. Fungsi json_encode() PHP boleh menukar tatasusunan atau objek kepada rentetan JSON. Artikel ini akan memperkenalkan cara menggunakan fungsi json_encode() PHP, termasuk sintaks, parameter, nilai pulangan dan contoh khusus. Sintaks Sintaks fungsi json_encode() adalah seperti berikut: st

Wedge Kita tahu bahawa objek dicipta dalam dua cara utama, satu adalah melalui Python/CAPI, dan satu lagi adalah dengan memanggil objek jenis. Contohnya objek jenis terbina dalam, kedua-dua kaedah disokong Contohnya, senarai boleh dibuat melalui [] atau list(). Tetapi sebagai contoh objek kelas tersuai, kita hanya boleh menciptanya dengan memanggil objek jenis. Jika objek boleh dipanggil, maka objek itu boleh dipanggil, jika tidak, ia tidak boleh dipanggil. Menentukan sama ada objek boleh dipanggil bergantung pada sama ada kaedah ditakrifkan dalam objek jenis sepadannya. suka

Begini cara untuk menukar tatasusunan hasil pertanyaan MySQL kepada objek: Cipta tatasusunan objek kosong. Gelung melalui tatasusunan yang terhasil dan buat objek baharu untuk setiap baris. Gunakan gelung foreach untuk menetapkan pasangan nilai kunci setiap baris kepada sifat yang sepadan bagi objek baharu. Menambah objek baharu pada tatasusunan objek. Tutup sambungan pangkalan data.

Gunakan fungsi __contains__() Python untuk mentakrifkan operasi pembendungan objek Python ialah bahasa pengaturcaraan ringkas dan berkuasa yang menyediakan banyak ciri berkuasa untuk mengendalikan pelbagai jenis data. Salah satunya adalah untuk melaksanakan operasi pembendungan objek dengan mentakrifkan fungsi __contains__(). Artikel ini akan memperkenalkan cara menggunakan fungsi __contains__() untuk mentakrifkan operasi pembendungan objek, dan memberikan beberapa kod sampel. Fungsi __contains__() ialah Pytho

Dalam PHP, tatasusunan ialah urutan tersusun, dan elemen diakses mengikut indeks; Akses tatasusunan adalah melalui indeks, akses objek adalah melalui sifat/kaedah. Nilai tatasusunan diluluskan dan rujukan objek diluluskan.

Tajuk: Menggunakan fungsi __le__() Python untuk menentukan perbandingan kurang daripada atau sama bagi dua objek Dalam Python, kita boleh mentakrifkan operasi perbandingan antara objek dengan menggunakan kaedah khas. Salah satunya ialah fungsi __le__(), yang digunakan untuk menentukan perbandingan kurang daripada atau sama. Fungsi __le__() ialah kaedah ajaib dalam Python dan merupakan fungsi khas yang digunakan untuk melaksanakan operasi "kurang daripada atau sama". Apabila kita membandingkan dua objek menggunakan operator kurang daripada atau sama (<=), Python

Perbezaan antara salinan cetek dan salinan dalam: Salinan cetek: Cipta objek yang merujuk data yang sama dan perubahan pada salinan juga akan mempengaruhi objek asal. Salinan dalam: Buat objek yang mengandungi salinan data objek asal Menukar salinan tidak akan menjejaskan objek asal.

Objek Permintaan dalam PHP ialah objek yang digunakan untuk mengendalikan permintaan HTTP yang dihantar oleh klien ke pelayan. Melalui objek Permintaan, kami boleh mendapatkan maklumat permintaan pelanggan, seperti kaedah permintaan, maklumat pengepala permintaan, parameter permintaan, dsb., untuk memproses dan membalas permintaan tersebut. Dalam PHP, anda boleh menggunakan pembolehubah global seperti $_REQUEST, $_GET, $_POST, dll. untuk mendapatkan maklumat yang diminta, tetapi pembolehubah ini bukan objek, tetapi tatasusunan. Untuk memproses maklumat permintaan dengan lebih fleksibel dan mudah, anda boleh
