首先,咱們仍是舉個例子來講明對象賦值操做的問題吧:
ps: 本文默認約定log = console.log
javascript
function A(){} A.prototype.x = 10; var a1 = new A(); A.prototype = { x: 20, y: 20 }; var a2 = new A(); log([a1.x, a1.y, a2.x, a2.y]); // [10, undefined, 20, 20]
js中對象賦值操做咱們能夠經過c語言中得指針概念來解釋。java
直接經過賦值操做符「=」將變量a中的對象賦值給變量b,此時咱們更改a、b其中一個,另外一個也會隨之更改。數組
var a = [1, 1], b = a; b[0] = 2; log(a[0]); // 2
由於咱們在將a的對象賦值給b時,js引擎內部的操做只是簡單的將a所指的對象的地址賦值給b,此時a與b指向內存中同一個對象,因此纔會出現這種狀況。這種賦值方式稱爲對象的淺拷貝。
咱們能夠從另外一個方面論證咱們的觀點:prototype
log(a === b); // true,毫無疑問 var c = [2, 1]; log(a === c); // false
出現這種狀況的緣由就是變量c指向的是另外一個和變量a指向的對象的值相同的對象,僅僅只是兩個指向的對象的值相同,但兩個對象在內存的地址是不同的,因此是false。
另外,咱們知道js數組中有一些方法能夠實現數組的徹底複製,即兩個變量分別指向兩個對象:指針
b = a.concat([]), c = a.slice(0), d = a.splice(0, a.length); log(b === a); // false
可是咱們要針對對象進行復制的話,只能手動進行模擬,即所謂的對象深拷貝。code
顧名思義,就是利用「=」對於基本類型的操做不存在上述問題,經過for-in深度遍歷對象的屬性,而後將其賦值給另外一個新的對象。對象
function cloneObj(obj) { var tempObj = {}; if (obj instanceof Array) { tempObj = []; } for (var prop in obj) { if (typeof prop === 'Object') { cloneObj(prop); } tempObj[prop] = obj[prop]; } return tempObj; } var myCountry = { name: 'China', birth: 1949 }, country = cloneObj(myCountry); log(country === myCountry); // false
最後,咱們回到第一個例子,會發現,引擎內部對於new對象的原型鏈也是經過簡單的賦值操做的方式,即對象的淺拷貝。而ES5新增的Object.create()
也是淺拷貝的一種封裝:ip
var myCountry = { name: 'China', birth: 1949 }, country = Object.create(myCountry); console.log(country.__proto__ === myCountry); // true