亚洲精品久久久久久第一页-人妻少妇精彩视品一区二区三区-91国产自拍免费视频-免费一级a在线播放视频正片-少妇天天日天天射天天爽-国产大屁股喷水视频在线观看-操美女骚穴抽插性爱视频-亚洲 欧美 中文字幕 丝袜-成人免费无码片在线观看

js深拷貝和淺拷貝的區(qū)別 js實現(xiàn)深拷貝的方法


js深拷貝和淺拷貝的區(qū)別 js實現(xiàn)深拷貝的方法

文章插圖
在實際開發(fā)當(dāng)中,我們經(jīng)常會遇到要對對象進行深拷貝的情況 。而且深拷貝這個問題在面試過程中也經(jīng)常會遇到,下面就對本人在學(xué)習(xí)過程中的收獲,做以簡單的總結(jié) 。
什么是淺拷貝,什么是深拷貝?什么是淺拷貝關(guān)于淺拷貝的概念,我在網(wǎng)上看到一種說法,直接上代碼 。
var person = {name: "Jason", age: 18, car: {brand: "Ferrari", type: "430"}};var person1 = person;//他們認為這是淺拷貝但是我個人認為,上面這個根本不涉及拷貝,只是一個簡單的引用賦值 。以我的理解,淺拷貝應(yīng)該是不考慮對象的引用類型的屬性,只對當(dāng)前對象的所有成員進行拷貝,代碼如下:
function copy(obj){var objCopy = {};for(var key in obj){objCopy[key] = obj[key];}return objCopy;}var person = {name: "Jason", age: 18, car: {brand: "Ferrari", type: "430"}};var personCopy = copy(person);上面這段代碼中,person對象擁有兩個基本類型的屬性name和age,一個引用類型的屬性car,當(dāng)使用如上方法進行拷貝的時候,name和age屬性會被正常的拷貝,但是car屬性,只會進行引用的拷貝,這樣會導(dǎo)致拷貝出來的對象personCopy和person會共用一個car對象 。這樣就是所謂的淺拷貝 。
什么是深拷貝深拷貝的就是在拷貝的時候,需要將當(dāng)前要拷貝的對象內(nèi)的所有引用類型的屬性進行完整的拷貝,也就是說拷貝出來的對象和原對象之間沒有任何數(shù)據(jù)是共享的,所有的東西都是自己獨占的一份 。
如何實現(xiàn)深拷貝實現(xiàn)深拷貝需要考慮的問題實現(xiàn)深拷貝需要考慮如下幾個因素:
傳入的對象是使用對象字面量{}創(chuàng)建的對象還是由構(gòu)造函數(shù)生成的對象如果對象是由構(gòu)造函數(shù)創(chuàng)建出來的,那么是否要拷貝原型鏈上的屬性如果要拷貝原型鏈上的屬性,那么如果原型鏈上存在多個同名的屬性,保留哪個處理循環(huán)引用的問題第三方庫實現(xiàn)深拷貝jQuery的$.extend()我們可以通過$.extend()方法來完成深復(fù)制 。值得慶幸的是,我們在jQuery中可以通過添加一個參數(shù)來實現(xiàn)遞歸extend 。調(diào)用$.extend(true, {}, …)就可以實現(xiàn)深復(fù)制,參考下面的例子:
var x = {a: 1,b: { f: { g: 1 } },c: [ 1, 2, 3 ]};var y = $.extend({}, x),//shallow copyz = $.extend(true, {}, x);//deep copyy.b.f === x.b.f// truez.b.f === x.b.f// false但是jQuery的這個$.extend()方法,有弊端,什么弊端呢?我們看下面的例子:
var objA = {};var objB = {};objA.b = objB;objB.a = objA;$.extend(true,{},a);//這個時候就出現(xiàn)異常了//Uncaught RangeError: Maximum call stack size exceeded(…)也就是說,jQuery中的$.extend()并沒有處理循環(huán)引用的問題 。
使用JSON對象實現(xiàn)深拷貝使用JSON全局對象的parse和stringify方法來實現(xiàn)深復(fù)制也算是一個簡單討巧的方法 。
function jsonClone(obj) {return JSON.parse(JSON.stringify(obj));}var clone = jsonClone({ a:1 });然而使用這種方法會有一些隱藏的坑,它能正確處理的對象只有 Number, String, Boolean, Array, 扁平對象,即那些能夠被 json 直接表示的數(shù)據(jù)結(jié)構(gòu) 。
自己造輪子下面我們給出一個簡單的解決方案,當(dāng)然這個方案是參考別人的方式來實現(xiàn)的 。希望對大家有用 。
var clone = (function() {//這個方法用來獲取對象的類型 返回值為字符串類型 "Object RegExp Date Array..."var classof = function(o) {if (o === null) {return "null";}if (o === undefined) {return "undefined";}// 這里的Object.prototype.toString很可能用的就是Object.prototype.constructor.name// 這里使用Object.prototype.toString來生成類型字符串var className = Object.prototype.toString.call(o).slice(8, -1);return className;};//這里這個變量我們用來存儲已經(jīng)保存過的屬性,目的在于處理循環(huán)引用的問題var references = null;//遇到不同類型的對象的處理方式var handlers = {//正則表達式的處理'RegExp': function(reg) {var flags = '';flags += reg.global ? 'g' : '';flags += reg.multiline ? 'm' : '';flags += reg.ignoreCase ? 'i' : '';return new RegExp(reg.source, flags);},//時間對象處理'Date': function(date) {return new Date(+date);},//數(shù)組處理 第二個參數(shù)為是否做淺拷貝'Array': function(arr, shallow) {var newArr = [],i;for (i = 0; i < arr.length; i++) {if (shallow) {newArr[i] = arr[i];} else {//這里我們通過reference數(shù)組來處理循環(huán)引用問題if (references.indexOf(arr[i]) !== -1) {continue;}var handler = handlers[classof(arr[i])];if (handler) {references.push(arr[i]);newArr[i] = handler(arr[i], false);} else {newArr[i] = arr[i];}}}return newArr;},//正常對象的處理 第二個參數(shù)為是否做淺拷貝'Object': function(obj, shallow) {var newObj = {}, prop, handler;for (prop in obj) {//關(guān)于原型中屬性的處理太過復(fù)雜,我們這里暫時不做處理//所以只對對象本身的屬性做拷貝if (obj.hasOwnProperty(prop)) {if (shallow) {newObj[prop] = obj[prop];} else {//這里還是處理循環(huán)引用的問題if (references.indexOf(obj[prop]) !== -1) {continue;}handler = handlers[classof(obj[prop])];//如果沒有對應(yīng)的處理方式,那么就直接復(fù)制if (handler) {references.push(obj[prop]);newObj[prop] = handler(obj[prop], false);} else {newObj[prop] = obj[prop];}}}}return newObj;}};return function(obj, shallow) {//首先重置我們用來處理循環(huán)引用的這個變量references = [];//我們默認處理為淺拷貝shallow = shallow === undefined ? true : false;var handler = handlers[classof(obj)];return handler ? handler(obj, shallow) : obj;};}());(function() {//下面是一些測試代碼var date = new Date();var reg = /hello word/gi;var obj = {prop: 'this ia a string',arr: [1, 2, 3],o: {wow: 'aha'}};var refer1 = {arr: [1, 2, 3]};var refer2 = {refer: refer1};refer1.refer = refer2;var cloneDate = clone(date, false);var cloneReg = clone(reg, false);var cloneObj = clone(obj, false);alert((date !== cloneDate) && (date.valueOf() === cloneDate.valueOf()));alert((cloneReg !== reg) && (reg.toString() === cloneReg.toString()));alert((obj !== cloneObj) && (obj.arr !== cloneObj.arr) && (obj.o !== cloneObj.o) && (JSON.stringify(obj) === JSON.stringify(cloneObj)));clone(refer2, false);alert("I'm not dead yet!");// Output:// true// true// true// I'm not dead yet!}());


以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問題,請您及時就醫(yī)或請專業(yè)人士給予相關(guān)指導(dǎo)!

「愛刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對您有所幫助: