日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

EcmaScript对象克隆之谜

發(fā)布時間:2023/12/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EcmaScript对象克隆之谜 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

低配版深拷貝

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var deepClone = function(currobj){if(typeof currobj !== 'object'){return currobj;}if(currobj instanceof Array){var newobj = [];}else{var newobj = {}}for(var key in currobj){if(typeof currobj[key] !== 'object'){newobj[key] = currobj[key];}else{newobj[key] = deepClone(currobj[key]) }}return newobj }

嘖嘖真是很精巧啊!對于Array和普通Object都做了區(qū)分。但是顯然,借助遞歸實(shí)現(xiàn)的深拷貝如果要克隆層級很多的復(fù)雜對象,容易造成內(nèi)存溢出,咱可以做出一個小小改進(jìn):

看起來酷一點(diǎn)的深拷貝

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 var deepClone = function(currobj){if(typeof currobj !== 'object'){return currobj;}if(currobj instanceof Array){var newobj = [];}else{var newobj = {}}var currQue = [currobj], newQue = [newobj]; //關(guān)鍵在這里while(currQue.length){var obj1 = currQue.shift(),obj2 = newQue.shift();for(var key in obj1){if(typeof obj1[key] !== 'object'){obj2[key] = obj1[key];}else{if(obj1[key] instanceof Array ){obj2[key] = [];}else{obj2[key] = {}};// 妙啊currQue.push(obj1[key]);newQue.push(obj2[key]);}}}return newobj; };

這里利用了兩個隊(duì)列,還算優(yōu)雅的避免了遞歸的弊端。

JSON序列化

還有一種方法是利用JSON的內(nèi)置方法,即所謂的JSON序列化:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var deepClone = function(obj){var str, newobj = obj.constructor === Array ? [] : {};if(typeof obj !== 'object'){return;} else if(window.JSON){str = JSON.stringify(obj), //系列化對象newobj = JSON.parse(str); //還原} else {for(var i in obj){newobj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]; }}return newobj; };

不過不打緊,它與上面方法的效果基本相同。

上面幾種深拷貝的局限

拜托,大家都很懂對象,上面的方法有幾個很大的問題:

  • 遇到對象內(nèi)部的循環(huán)引用直接gg
  • 無法拷貝函數(shù)(typeof 函數(shù) 得到的是 ‘function’),函數(shù)仍是引用類型
  • 無法正確保留實(shí)例對象的原型

于是,我們就要開始改造上面的深拷貝方法來進(jìn)行完美的克隆了!………….么?

等下,你到底要啥

克隆克隆,我們平常把它掛在嘴上,但面對一個對象,我們真正想克隆的是什么?我想在99%的情況下,我們想克隆的是對象的數(shù)據(jù),而保留它的原型引用方法引用,因此上面提到的局限中的第二點(diǎn),基本可以不考慮?,F(xiàn)在咱再來看看怎么解決剩下兩點(diǎn)。

解決循環(huán)引用

首先搞清什么是循環(huán)引用,常見的循環(huán)引用有兩種:

自身循環(huán)引用

1 2 var a = {}; a._self = a;

這種循環(huán)引用可以說很是常見。

多個對象互相引用

1 2 3 4 var a = {}; var b = {}; a.brother = b; b.brother = a;

也不是沒見過,不過這是典型導(dǎo)致對象內(nèi)存無法被回收的寫法,本身就不推薦。

解決之道

目前只找到了針對第一種引用的解決方法,來自于Jquery源碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 jQuery.extend = jQuery.fn.extend = function() {// options是一個緩存變量,用來緩存arguments[i]// name是用來接收將要被擴(kuò)展對象的key// src改變之前target對象上每個key對應(yīng)的value// copy傳入對象上每個key對應(yīng)的valu// copyIsArray判定copy是否為一個數(shù)組// clone深拷貝中用來臨時存對象或數(shù)組的srcvar options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},i = 1,length = arguments.length,deep = false;// 處理深拷貝的情況if (typeof target === "boolean") {deep = target;target = arguments[1] || {};//跳過布爾值和目標(biāo) i++;}// 控制當(dāng)target不是object或者function的情況if (typeof target !== "object" && !jQuery.isFunction(target)) {target = {};}// 當(dāng)參數(shù)列表長度等于i的時候,擴(kuò)展jQuery對象自身if (length === i) {target = this; --i;}for (; i < length; i++) {if ((options = arguments[i]) != null) {// 擴(kuò)展基礎(chǔ)對象for (name in options) {src = target[name]; copy = options[name];// 防止永無止境的循環(huán),這里舉個例子,如var i = {};i.a = i;$.extend(true,{},i);如果沒有這個判斷變成死循環(huán)了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存在且是數(shù)組的話就讓clone副本等于src否則等于空數(shù)組。} else {clone = src && jQuery.isPlainObject(src) ? src: {}; // 如果src存在且是對象的話就讓clone副本等于src否則等于空數(shù)組。}// 遞歸拷貝target[name] = jQuery.extend(deep, clone, copy);} else if (copy !== undefined) {target[name] = copy; // 若原對象存在name屬性,則直接覆蓋掉;若不存在,則創(chuàng)建新的屬性。}}}}// 返回修改的對象return target; };

解決原型的引用

在我們想辦法魔改深拷貝時,先看下以上這么多深拷貝的基本原理:

利用for-in循環(huán)遍歷對象屬性,如果屬性值是對象則深拷貝,不是則直接賦值

于是俺眉頭一皺發(fā)現(xiàn)事情并不簡單,俺上一篇博客已經(jīng)說明:for-in遍歷的是對象以及其原型鏈上可枚舉屬性,因此想在遍歷時對源對象的__proto__做手腳是根本不存在的,__proto__以及它的不可枚舉屬性根本不會被遍歷到??梢酝ㄟ^下面的例子看出:

1 2 3 4 5 6 7 8 9 10 11 12 13 var deepClone = function() {...} // 隨便從上面拿一個 var A = function() {this.val = 1; } A.prototype.log = function() {console.log(this.val); }var obj1 = new A(); var obj2 = deepClone(obj1);console.log(obj1); // A {val: 1} console.log(obj2); // {val: 1, log: function(){...}}

因此,一個解決方法很單純,就是像上面的jQuery.extend方法一樣,自己傳入拷貝的目標(biāo)對象,extend方法本質(zhì)上只是拓展目標(biāo)對象的屬性,使其獲得源對象上的數(shù)據(jù),這樣一來只要我們先創(chuàng)建好符合需求的目標(biāo)對象即可。

另一種方法則是不采用深拷貝,直接取出需要進(jìn)行拷貝的對象的數(shù)據(jù),然后再利用這份數(shù)據(jù)來實(shí)例化和設(shè)置一個新的對象出來

1 2 3 4 5 6 7 8 9 10 11 var Foo = function( obj ){this.name = obj.name;this.sex = obj.sex };Foo.prototype.toJSON = funciton(){return { name: this.name, sex: this.sex }; };var foo = new Foo({ name: "bandit", sex: "male" }); var fooCopy = new Foo( foo.toJSON() );

問題同樣得到解決【鼓掌】


回顧一下,沒有哪種方法是萬用的魔法 —— 在我們想要獲得一個克隆對象之前,或許最好先搞清楚我們到底是在克隆什么,再采用最適合的方法。而非是拘泥于“深拷貝淺拷貝”的說法,去復(fù)制一段代碼祈禱他能生效。我相信以上的示例代碼還沒有考慮到克隆對象的所有問題,但它們在合適的場景下能夠處理合適的問題。嗯,其實(shí)很多事情都是這樣蛤【帶!】

轉(zhuǎn)載于:https://www.cnblogs.com/jinhengyu/p/10257781.html

總結(jié)

以上是生活随笔為你收集整理的EcmaScript对象克隆之谜的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日皮视频在线观看 | 久久小视频 | 国产黄色在线网站 | 黄色小视频在线免费观看 | 亚洲一区二区三区久久久成人动漫 | 人妻久久一区二区三区 | 操操操综合网 | www.狠狠| 筱田优全部av免费观看 | 五月天六月婷婷 | 日本一区二区不卡在线观看 | 刘玥91精选国产在线观看 | 国产欧美一区在线观看 | 艳母日本动漫在线观看 | 极品av在线 | 国产成人一区二区三区免费看 | 免费在线观看一区二区 | 国产精品成人无码专区 | 韩国女主播av | 亚洲精品乱码久久久久久不卡 | 胖女人做爰全过程 | 免费黄色小视频网站 | 精品国产乱码久久久人妻 | 黄色在线免费网站 | 好吊妞在线观看 | 亚洲男男网站 | 免费av一级| 韩国jizz| 国产一二区在线观看 | 91视频官网 | 日韩在线观看免费高清 | 激情五月色婷婷 | 日韩在线二区 | 在线免费视频一区 | 伊人9 | 北条麻妃在线一区二区 | 欧洲精品久久 | 国产成人精品白浆久久69 | 日本欧美国产一区二区三区 | 久久乐av | 深夜福利免费视频 | av免费观看入口 | 日本黄色片视频 | 免费黄色av网站 | 亚洲av乱码久久精品蜜桃 | www.四虎com | 91日韩视频 | 久草免费资源 | 欧美黄在线观看 | 交做爰xxxⅹ性爽 | 99久久精品国产一区二区三区 | 日韩欧美一区二区三区免费观看 | 国产欧美在线观看视频 | 殴美一级黄色片 | 国产妇女乱一性一交 | 99热热 | 福利在线一区二区 | 99久久视频 | 日本天堂在线视频 | 91av福利| 久久欧美视频 | 在线观看成人动漫 | 老司机福利院 | 黄色片aa| 国产交换配乱淫视频免费 | 国产黄 | 亚洲精品乱码久久久久久国产主播 | 久久91精品 | 东北高大丰满bbbbzbbb | 精品欧美一区二区精品少妇 | 国产天天综合 | 操出白浆视频 | 亚洲黄色a | 国产91久| 啪免费视频 | 亚洲一区天堂 | 在线观看麻豆视频 | 午夜性色福利影院 | 亚洲制服丝袜av | 亚洲黄网在线 | 国产一区视频在线免费观看 | 18我禁在线观看 | 国产三级在线看 | 又爽又黄视频 | 国产成年人视频网站 | 亚洲第一看片 | 天天操天天射天天爽 | 91九色丨porny丨国产jk | 成人精品久久久午夜福利 | 国产午夜亚洲精品午夜鲁丝片 | 17c一起操 | 四虎影视www在线播放 | 超碰在线免费97 | 久久这里只有精品6 | 国产二区av | 人人澡人人草 | 欧美女同在线 | 国产精品久久久久久三级 | 久久精品在这里 |