本文為大家分享了JavaScript物件的淺拷貝和深拷貝程式碼,供大家參考,具體內容如下
1.淺拷貝
拷貝就是把父對像的屬性,全部拷貝給子物件。
下面這個函數,就是在做拷貝:
var Chinese = { nation:'中国' } var Doctor = { career:'医生' } function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c; }
使用的時候,這樣寫:
var Doctor = extendCopy(Chinese); Doctor.career = '医生'; alert(Doctor.nation); // 中国
但是,這樣的拷貝有一個問題。那就是,如果父對象的屬性等於數組或另一個對象,那麼實際上,子對象獲得的只是一個記憶體地址,而不是真正拷貝,因此存在父對像被篡改的可能。
請看,現在給Chinese加上一個」出生地」屬性,它的值是一個陣列。
Chinese.birthPlaces = ['北京','上海','香港'];
透過extendCopy()函數,Doctor繼承了Chinese。
var Doctor = extendCopy(Chinese);
然後,我們為Doctor的」出生地」增加一個城市:
Doctor.birthPlaces.push('廈門');
Doctor.birthPlaces.push('廈門');
Doctor.birthPlaces.push('廈門');
alert(Chinese.birthPlaces); //北京, 上海, 香港, 廈門
結果是兩個的出生地都被改了。
所以,extendCopy() 只是拷貝了基本類型的數據,我們把這種拷貝叫做「淺拷貝」。
2.深拷貝
因為淺深拷貝如此弊端所以我們接下來看一下深拷貝
所謂”深拷貝”,就是能夠實現真正意義上的數組和對象的拷貝。它的實作並不難,只要遞歸呼叫」淺拷貝」就行了。
function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; } } return c; }
看一下使用方法:
var Doctor = deepCopy(Chinese);
現在,為父物件加一個屬性,值為陣列。然後,在子物件上修改這個屬性:
Chinese.birthPlaces = ['北京','上海','香港']; Doctor.birthPlaces.push('厦门'); alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门 alert(Chinese.birthPlaces); //北京, 上海, 香港
這樣就完成了拷貝;
$.extend()
jquery 中$.extend()如同。
•deep
類型: Boolean
如果是true,合併成為遞歸(又叫做深拷貝)。
•target
類型: Object
物件擴充。這將接收新的屬性。
•object1
類型: Object
一個對象,它包含額外的屬性合併到第一個參數.
•objectN
類型: Object
類型: Object
包含額外的屬性合併到第一個參數 多個物件給$.extend(),物件的所有屬性都會加入目標物件(target參數)。 如果只有一個參數提供給$.extend(),這表示目標參數被省略。在這種情況下,jQuery物件本身被預設為目標物件。這樣,我們可以在jQuery的命名空間下加入新的功能。這對於外掛程式開發者希望在 jQuery 中新增函數時是很有用的。 請記住,目標物件(第一個參數)將被修改,並且將透過$.extend()傳回。然而,如果我們想要保留原對象,我們可以透過傳遞一個空對像作為目標對象:var object = $.extend({}, object1, object2);在預設情況下,透過$.extend()合併操作不是遞歸的;如果第一個物件的屬性本身是一個物件或數組,那麼它將完全用第二個物件相同的key重寫一個屬性。這些值不會被合併。可以透過檢查下面例子中 banana 的值,就可以了解這一點。然而,如果將 true 作為該函數的第一個參數,那麼就會在物件上進行遞歸的合併。 警告:不支援第一個參數傳遞 false 。 1. 合併兩個對象,並修改第一個對象。var object1 = { apple: 0, banana: { weight: 52, price: 100 }, cherry: 97 }; var object2 = { banana: { price: 200 }, durian: 100 }; // Merge object2 into object1 $.extend( object1, object2 ); // Assuming JSON.stringify - not available in IE<8 console.log( JSON.stringify( object1 ) ); //{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
var object1 = { apple: 0, banana: { weight: 52, price: 100 }, cherry: 97 }; var object2 = { banana: { price: 200 }, durian: 100 }; // Merge object2 into object1, recursively $.extend( true, object1, object2 ); // Assuming JSON.stringify - not available in IE<8 console.log( JSON.stringify( object1 ) ); //{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}
var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; // Merge defaults and options, without modifying defaults var settings = $.extend( {}, defaults, options ); console.log(JSON.stringify( defaults )); console.log(JSON.stringify( options )); console.log(JSON.stringify( settings )); //defaults -- {"validate":false,"limit":5,"name":"foo"} //options -- {"validate":true,"name":"bar"} //settings -- {"validate":true,"limit":5,"name":"bar"}
var obj1 = { name: "Benjamin", sex : "male" } var obj2 = { name: "Benjamin", sex : "male" } //Outputs: false console.log(obj1 == obj2); //Outputs: false console.log(obj1 === obj2);
var obj1 = { name: "Benjamin", sex : "male" }; var obj2 = { name: "Benjamin", sex : "male" }; var obj3 = obj1; //Outputs: true console.log(obj1 == obj3); //Outputs: true console.log(obj1 === obj3); //Outputs: false console.log(obj2 == obj3); //Outputs: false console.log(obj2 === obj3);
function person(name) { this.name=name; } var p1 = new person("p1"); var p2 = new person("p2"); console.log(p1 == p2); //false person.prototype.sayHi = function() { // do sayHi here } console.log(p1.sayHi() == p2.sayHi()); //true console.log(p1.sayHi() === p2.sayHi()); //true