亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

淺析javaScript中的淺拷貝和深拷貝

2019-11-19 17:34:35
字體:
來源:轉載
供稿:網友

1、javaScript的變量類型

(1)基本類型:

5種基本數據類型Undefined、Null、Boolean、Number 和 String,變量是直接按值存放的,存放在棧內存中的簡單數據段,可以直接訪問。

(2)引用類型:

存放在堆內存中的對象,變量保存的是一個指針,這個指針指向另一個位置。當需要訪問引用類型(如對象,數組等)的值時,首先從棧中獲得該對象的地址指針,然后再從堆內存中取得所需的數據。

JavaScript存儲對象都是存地址的,所以淺拷貝會導致 obj1 和obj2 指向同一塊內存地址。改變了其中一方的內容,都是在原來的內存上做修改會導致拷貝對象和源對象都發生改變,而深拷貝是開辟一塊新的內存地址,將原對象的各個屬性逐個復制進去。對拷貝對象和源對象各自的操作互不影響。

例如:數組拷貝

//淺拷貝,雙向改變,指向同一片內存空間var arr1 = [1, 2, 3];var arr2 = arr1;arr1[0] = 'change';console.log('shallow copy: ' + arr1 + " ); //shallow copy: change,2,3console.log('shallow copy: ' + arr2 + " ); //shallow copy: change,2,3

2、淺拷貝的實現

2.1、簡單的引用復制

function shallowClone(copyObj) { var obj = {}; for ( var i in copyObj) { obj[i] = copyObj[i]; } return obj;}var x = { a: 1, b: { f: { g: 1 } }, c: [ 1, 2, 3 ]};var y = shallowClone(x);console.log(y.b.f === x.b.f);  // true

2.2、Object.assign()

Object.assign() 方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然后返回目標對象。Object.assign會跳過那些值為 null 或 undefined 的源對象。

var x = { a: 1, b: { f: { g: 1 } }, c: [ 1, 2, 3 ]};var y = Object.assign({}, x);console.log(y.b.f === x.b.f);  // true

3、深拷貝的實現

3.1、Array的slice和concat方法

Array的slice和concat方法不修改原數組,只會返回一個淺復制了原數組中的元素的一個新數組。之所以把它放在深拷貝里,是因為它看起來像是深拷貝。而實際上它是淺拷貝。原數組的元素會按照下述規則拷貝:

  • 如果該元素是個對象引用 (不是實際的對象),slice 會拷貝這個對象引用到新的數組里。兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。
  • 對于字符串、數字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組里。在別的數組里修改這些字符串或數字或是布爾值,將不會影響另一個數組。

如果向兩個數組任一中添加了新元素,則另一個不會受到影響。例子如下:

var array = [1,2,3]; var array_shallow = array; var array_concat = array.concat(); var array_slice = array.slice(0); console.log(array === array_shallow); //true console.log(array === array_slice); //false,“看起來”像深拷貝console.log(array === array_concat); //false,“看起來”像深拷貝

可以看出,concat和slice返回的不同的數組實例,這與直接的引用復制是不同的。而從另一個例子可以看出Array的concat和slice并不是真正的深復制,數組中的對象元素(Object,Array等)只是復制了引用。如下:

var array = [1, [1,2,3], {name:"array"}]; var array_concat = array.concat();var array_slice = array.slice(0);array_concat[1][0] = 5; //改變array_concat中數組元素的值 console.log(array[1]); //[5,2,3] console.log(array_slice[1]); //[5,2,3] array_slice[2].name = "array_slice"; //改變array_slice中對象元素的值 console.log(array[2].name); //array_sliceconsole.log(array_concat[2].name); //array_slice

3.2、JSON對象的parse和stringify

JSON對象是ES5中引入的新的類型(支持的瀏覽器為IE8+),JSON對象parse方法可以將JSON字符串反序列化成JS對象,stringify方法可以將JS對象序列化成JSON字符串,借助這兩個方法,也可以實現對象的深拷貝。

//例1var source = { name:"source", child:{ name:"child" } } var target = JSON.parse(JSON.stringify(source));target.name = "target"; //改變target的name屬性console.log(source.name); //source console.log(target.name); //targettarget.child.name = "target child"; //改變target的child console.log(source.child.name); //child console.log(target.child.name); //target child//例2var source = { name:function(){console.log(1);}, child:{ name:"child" } } var target = JSON.parse(JSON.stringify(source));console.log(target.name); //undefined//例3var source = { name:function(){console.log(1);}, child:new RegExp("e") }var target = JSON.parse(JSON.stringify(source));console.log(target.name); //undefinedconsole.log(target.child); //Object {}

這種方法使用較為簡單,可以滿足基本的深拷貝需求,而且能夠處理JSON格式能表示的所有數據類型,但是對于正則表達式類型、函數類型等無法進行深拷貝(而且會直接丟失相應的值)。還有一點不好的地方是它會拋棄對象的constructor。也就是深拷貝之后,不管這個對象原來的構造函數是什么,在深拷貝之后都會變成Object。同時如果對象中存在循環引用的情況也無法正確處理。

4、jQuery.extend()方法源碼實現

jQuery的源碼 - src/core.js #L121源碼及分析如下:

jQuery.extend = jQuery.fn.extend = function() { //給jQuery對象和jQuery原型對象都添加了extend擴展方法var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; //以上其中的變量:options是一個緩存變量,用來緩存arguments[i],name是用來接收將要被擴展對象的key,src改變之前target對象上每個key對應的value。 //copy傳入對象上每個key對應的value,copyIsArray判定copy是否為一個數組,clone深拷貝中用來臨時存對象或數組的src。// 處理深拷貝的情況if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; //跳過布爾值和目標  i++;} // 控制當target不是object或者function的情況if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {};}// 當參數列表長度等于i的時候,擴展jQuery對象自身。if ( length === i ) { target = this; --i;}for ( ; i < length; i++ ) { if ( (options = arguments[ i ]) != null ) {  // 擴展基礎對象  for ( name in options ) {   src = target[ name ];   copy = options[ name ];   // 防止永無止境的循環,這里舉個例子,如var i = {};i.a = i;$.extend(true,{},i);如果沒有這個判斷變成死循環了   if ( target === copy ) {    continue;   }   if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {    if ( copyIsArray ) {     copyIsArray = false;     clone = src && jQuery.isArray(src) ? src : [];// 如果src存在且是數組的話就讓clone副本等于src否則等于空數組。    } else {     clone = src && jQuery.isPlainObject(src) ? src : {};// 如果src存在且是對象的話就讓clone副本等于src否則等于空數組。    }    // 遞歸拷貝    target[ name ] = jQuery.extend( deep, clone, copy );   } else if ( copy !== undefined ) {    target[ name ] = copy;// 若原對象存在name屬性,則直接覆蓋掉;若不存在,則創建新的屬性。   }  } }}// 返回修改的對象return target;};

jQuery的extend方法使用基本的遞歸思路實現了淺拷貝和深拷貝,但是這個方法也無法處理源對象內部循環引用,例如:

var a={"name":"aaa"};var b={"name":"bbb"};a.child=b;b.parent=a;$.extend(true,{},a);//直接報了棧溢出。Uncaught RangeError: Maximum call stack size exceeded

5、自己動手實現一個拷貝方法

var $ = (function(){ var types = 'Array Object String Date RegExp Function Boolean Number Null Undefined'.split(' '); function type() { return Object.prototype.toString.call(this).slice(8, -1); } for (var i = types.length; i--;) {  $['is' + types[i]] = (function (self) {  return function (elem) {   return type.call(elem) === self;  }; })(types[i]); } return $;})();//類型判斷function copy(obj,deep){  if(obj === null || typeof obj !== "object"){   return obj;  }       var name, target = $.isArray(obj) ? [] : {}, value;  for(name in obj){   value = obj[name];   if(value === obj) {  continue;  }  if(deep && ($.isArray(value) || $.isObject(value))){  target[name] = copy(value,deep);  }else{  target[name] = value;  }  }  return target;}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性高潮在线| 欧美在线性视频| 蜜臀久久99精品久久久无需会员| 日产精品久久久一区二区福利| 国产精品专区第二| 成人做爰www免费看视频网站| 欧美天天综合色影久久精品| 成人看片人aa| 国产一区二区三区四区福利| 国产日韩在线免费| 国产热re99久久6国产精品| 国产亚洲欧洲黄色| 中文字幕在线成人| 日韩av一区二区在线观看| 亚洲欧美变态国产另类| 91精品国产高清久久久久久久久| 中文字幕一区二区精品| 精品国产一区二区三区在线观看| 91在线视频导航| 欧美中文字幕在线观看| 综合av色偷偷网| 欧美激情视频在线观看| 深夜福利国产精品| 国内精品久久久久伊人av| 国产精品久久久久久久久粉嫩av| 国产ts一区二区| 韩国视频理论视频久久| 久久亚洲成人精品| 日本免费一区二区三区视频观看| 国产精品精品国产| 亚洲视频视频在线| 欧美华人在线视频| 日韩精品在线免费播放| 伊是香蕉大人久久| 欧美成人剧情片在线观看| 爱福利视频一区| 日韩av在线一区| 国产成+人+综合+亚洲欧美丁香花| 中文日韩电影网站| 在线亚洲欧美视频| 成人精品aaaa网站| 久久久亚洲福利精品午夜| 欧美老女人在线视频| 在线亚洲国产精品网| 2019中文字幕全在线观看| 亚洲欧美国产精品久久久久久久| 国产一区二区三区直播精品电影| 日韩在线视频免费观看| 国产精品久久久久久久久久| 久久久人成影片一区二区三区| 亚洲男人av电影| 岛国av在线不卡| 性欧美亚洲xxxx乳在线观看| 在线播放日韩欧美| 亚洲的天堂在线中文字幕| 久久久爽爽爽美女图片| 精品无码久久久久久国产| 欧美老少配视频| 日韩欧美综合在线视频| 国产成人精品免费久久久久| 久久好看免费视频| 色综合久久中文字幕综合网小说| 在线日韩第一页| 日韩的一区二区| 亚洲国产福利在线| 日韩av影视在线| 高潮白浆女日韩av免费看| 中文字幕国产精品久久| 亚洲午夜性刺激影院| 色综合91久久精品中文字幕| 欧美激情第一页xxx| 在线成人中文字幕| 亚洲国产欧美一区二区三区同亚洲| 精品高清一区二区三区| 欧美激情成人在线视频| 色一区av在线| 成人在线免费观看视视频| 免费成人高清视频| 色视频www在线播放国产成人| 国产精品久久久久久久美男| 久久精品国产成人精品| 亚洲美女av黄| 欧美日韩999| 92福利视频午夜1000合集在线观看| 日韩在线视频观看正片免费网站| 色婷婷av一区二区三区在线观看| 国产综合在线观看视频| 亚洲欧美999| 国产精品白丝av嫩草影院| 欧美精品日韩www.p站| 日韩av网址在线观看| 国产精品久久久久9999| 97精品在线观看| 亚洲第一男人av| 日韩va亚洲va欧洲va国产| 91免费视频国产| 91精品国产777在线观看| 精品久久久久久亚洲国产300| 国产又爽又黄的激情精品视频| 91影视免费在线观看| 久久亚洲电影天堂| 欧美亚洲视频一区二区| 亚洲成人1234| 欧美激情视频网址| 97色在线观看免费视频| 欧美日韩亚洲视频一区| 久久久久久91| 亚洲欧美日韩区| 亚洲综合社区网| 国产日韩在线看片| 国产亚洲精品久久久优势| 欧美精品在线免费播放| 奇米4444一区二区三区| 欧美精品一区三区| 国产一区二区三区三区在线观看| 日韩电影在线观看永久视频免费网站| 91网站免费观看| 国产精品永久免费在线| 最近2019年中文视频免费在线观看| 国产99在线|中文| 久久天天躁狠狠躁老女人| 在线观看视频99| 欧美日韩aaaa| 亚洲欧洲中文天堂| 伦理中文字幕亚洲| 美女精品视频一区| 成人中文字幕+乱码+中文字幕| 欧美电影院免费观看| 久久影院中文字幕| 久久久欧美一区二区| 欧美亚洲国产视频小说| 欧美极品第一页| 色无极亚洲影院| 久久久久国产精品一区| 少妇高潮 亚洲精品| 国产午夜精品美女视频明星a级| 国产亚洲一区二区在线| 国产日产欧美精品| 日韩视频免费中文字幕| 亚洲mm色国产网站| 91中文字幕一区| 668精品在线视频| 久久国产精品99国产精| www.美女亚洲精品| 国产成人精品日本亚洲| 日韩美女在线观看| 91精品国产乱码久久久久久蜜臀| 日本一区二区三区四区视频| 国产精品jizz在线观看麻豆| 日本久久久久亚洲中字幕| 中文字幕免费国产精品| 九九九久久国产免费| 亚洲精品美女在线观看| 久久久精品美女| 色妞久久福利网| 国产精品一区二区女厕厕| 欧美成人网在线| 久久全国免费视频| 少妇久久久久久| 精品毛片三在线观看| 欧美激情精品久久久久久蜜臀| 亚洲在线免费视频| 国产网站欧美日韩免费精品在线观看| 色综合久久天天综线观看|