在程式碼重複使用模式裡面有一種叫做「複製屬性模式」(copying properties pattern)。談到程式碼重複使用的時候,很有可能想到的是程式碼的繼承性(inheritance),但重要的是要記住其最終目標-我們要重複使用程式碼。繼承性只是實作程式碼復用的手段,而不是唯一的方法。複製屬性也是一種複用模式,它跟繼承性是有所不同的。在這種模式中,物件將從另外一個在物件中取得成員,其方法是僅需將其複製即可。用過jQuery的都知道,它有一個$.extend()方法,它的用途除了擴充第三方插件之外,還可以用來複製屬性的。下面我們來看一個extend()函數的實作程式碼(注意這裡的並不是jQuery的源碼,只是一個簡單的範例):
function extend(parent, child) { var i; //如果不传入第二参数child //那么就创建一个新的对象 child = child || {}; //遍历parent对象的所有属性 //并且过滤原型上的属性 //然后将自身属性复制到child对象上 for(i in parent) { if(parent.hasOwnProperty(i)) { child[i] = parent[i]; } } //返回目标对象child return child; }
上面的程式碼是一個簡單的實現,它只遍歷父物件的成員並將其複製到子物件中去。下面我們用上面的extend()方法來測試一下:
var dad = {name: "Adam"}; var kid = extend(dad); console.log(kid.name); //Adam
我們發現,extend()方法已經可以正常運作了。但是有一個問題,上面給出的是一種所謂的淺複製(shallow clone)。在使用淺複製的時候,如果改變了子對象的屬性,並且該屬性恰好又是一個對象,那麼這種操作也會修改父對象,單是很多情況這不是我們想要的結果。考慮下列情況:
var dad = { counts: [1, 2, 3], reads: {paper: true} }; var kid = extend(dad) //调用extend()方法将dad的属性复制到kid上面 kid.counts.push(4); //把4追加到kid.counts数组里面 console.log(dad.counts); //[1, 2, 3, 4]
透過上面的例子,我們會發現,修改了kid.counts屬性以後(把元素4追加進去了),dad.counts也會受到影響。這是因為在使用淺複製的時候,由於物件是透過引用傳遞的,即kid.counts和dad.counts指向的是同一個陣列(或者說在記憶體上他們指向同一個堆的位址)。
下面,讓我們修改extend()函數以實現深度複製。我們需要做的事情就是檢查父物件的每一個屬性,如果該屬性恰好是物件的話,那麼就遞歸複製出該物件的屬性。另外,還需要偵測該物件是否為一個數組,這是因為數組的字面量創建方式和物件的字面量創建方式不一樣,前者是[],後者是{}。檢測陣列可以使用Object.prototype.toString()方法進行檢測,如果是陣列的話,他會回傳"[object Array]"。下面我們來看看深度複製版本的extend()函數:
function extendDeep(parent, child) { child = child || {}; for(var i in parent) { if(parent.hasOwnProperty(i)) { //检测当前属性是否为对象 if(typeof parent[i] === "object") { //如果当前属性为对象,还要检测它是否为数组 //这是因为数组的字面量表示和对象的字面量表示不同 //前者是[],而后者是{} child[i] = (Object.prototype.toString.call(parent[i]) === "[object Array]") ? [] : {}; //递归调用extend extendDeep(parent[i], child[i]); } else { child[i] = parent[i]; } } } return child; }
好了,深度複製的函數已經寫好了,下面來測試一下看是否能夠預期那樣子工作,即是否可以實現深度複製:
var dad = { counts: [1, 2, 3], reads: {paper: true} }; var kid = extendDeep(dad); //修改kid的counts属性和reads属性 kid.counts.push(4); kid.reads.paper = false; console.log(kid.counts); //[1, 2, 3, 4] console.log(kid.reads.paper); //false console.log(dad.counts); //[1, 2, 3] console.log(dad.reads.paper); //true
透過上面例子,我們可以發現,即使修改了子物件的kid.counts和kid.reads,父物件的dad.counts和kid.reads並沒有改變,因此我們的目的實現了。
下面來總結實現深複製的基本想法:
1.偵測目前屬性是否為物件
2.因為數組是特殊的對象,所以,在屬性為對象的前提下還需要偵測它是否為數組。
3.如果是數組,則建立一個[]空數組,否則,建立一個{}空對象,並賦值給子對象的目前屬性。然後,遞歸呼叫extendDeep函數。
上面範例使我們自己使用遞歸演算法實現的一種深度複製方法。事實上,ES5新增的JSON物件提供的兩個方法也可以實現深度複製,分別是JSON.stringify()和JSON.parse();前者用來將物件轉成字串,後者則把字串轉換成物件。下面我們使用此方法來實作一個深度複製的函數:
function extendDeep(parent, child) { var i, proxy; proxy = JSON.stringify(parent); //把parent对象转换成字符串 proxy = JSON.parse(proxy) //把字符串转换成对象,这是parent的一个副本 child = child || {}; for(i in proxy) { if(proxy.hasOwnProperty(i)) { child[i] = proxy[i]; } } proxy = null; //因为proxy是中间对象,可以将它回收掉 return child; }
下面是測試範例:
var dad = { counts: [1, 2, 3], reads: {paper: true} }; var kid = extendDeep(dad); //修改kid的counts属性和reads属性 kid.counts.push(4); kid.reads.paper = false; console.log(kid.counts); //[1, 2, 3, 4] console.log(kid.reads.paper); //false console.log(dad.counts); //[1, 2, 3] console.log(dad.reads.paper); //true
測試發現,它也實現了深度複製。一般建議使用後面這種方法,因為JSON.parse和JSON.stringify是內建函數,處理起來會比較快。另外,前面的那種方法使用了遞歸調用,我們都知道,遞歸是效率比較低的演算法。
關於JavaScript深度複製(deep clone)的實作方法就跟大家介紹這麼多,希望對大家有幫助!

javaandjavascriptaredistinctlanguages:javaisusedforenterpriseandmobileapps,while javascriptifforInteractiveWebpages.1)JavaisComcompoppored,statieldinglationallyTypted,statilly tater astrunsonjvm.2)

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3漢化版
中文版,非常好用

Dreamweaver CS6
視覺化網頁開發工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境