阮一峯博客,戳這裏javascript
上一篇:JavaScript面向對象之二(構造函數繼承)html
讀了這三篇大佬的博客以後,忽然頓悟,繼承說白了就是對原型鏈的拷貝(笨笨的),由於這一篇基本扒開了,最後直接赤裸裸的拷貝嘛。java
var Animal = {
type: 'animal'
}
var cat = {
name: 'po'
}
複製代碼
這裏是兩個對象,而不是兩個構造函數,這樣來去繼承就是非構造函數的繼承,那麼該怎麼作呢?數組
先到這裏,再再再提一次new作了哪些事,這個在理解繼承中很重要!bash
//例如 new Animal()
var temp = {}
temp.__proto__ = Animal.prototype
Animal.call(temp)
return temp
複製代碼
new主要是將實例的__proto__
指向了上級的prototype
。函數
而後來看看空對象繼承是怎麼作的?post
function object(obj){
function Fn(){} //建立了一個空函數
fn.prototype = obj //而後將要繼承的obj放到空函數的prototype
return new Fn() //而後返回這個空函數的實例
}
複製代碼
知道了上面這兩點,咱們再來逐步分析ui
var xxx = object(Animal)
複製代碼
執行object函數,傳入Animal,咱們知道object函數返回的是裏面空函數的實例,因此xxx.__proto__ = Fn.prototype
,而後Fn的prototype又是咱們的Animal,緣由是這一句fn.prototype = obj
,這樣一來xx.__proto__ = Animal
。spa
作到這個地步以後,xxx沒有的屬性,就會經過自身的__proto__去上一層去找,就會找到Animal。這樣一來就是集成父對象的屬性了。prototype
這種方式就直接粗暴的去父對象裏面的拷貝,我沒有,我就直接從你身上拿就能夠了。
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
複製代碼
這樣會有一個問題,父對象屬性裏面是一個對象或者數組的時候機會出現問題,由於是淺拷貝,拷貝的是數組或者對象的引用,這樣一來,繼承的子對象,若是修改了這類屬性,就會對父對象裏面響應的屬性產生影響,因而咱們須要深拷貝。
function deepClone(child, father){
var child = child || {}
var toStr = Object.prototype.toString
for(var key in father){
if(father.hasOwnProperty(key)){
if(typeof(father[key]) === 'object' && father[key] !== null){
//Object.assign(child[key] = father[key].prototype.constructor === Array?[]:{}, father[key])
if(toStr.call(father[key]) === '[object, Object]'){
child[key] = {}
}else{
child[key] = []
}
deepClone(child[key], father[key])
}else{
child[key] = father[key]
}
}
}
return child
}
複製代碼
另外,Object.assign是一種介於淺拷貝和深拷貝之間的一種形式,千萬不要把它當作深拷貝! 若是是正則、日期什麼的就須要另行判斷。好了,到這裏就差很少了。
其實繼承並非什麼難題,無非兩種:一種是我沒有,就去你身上找;或者是從你身上拿到個人身上,這樣我就有了。這樣理解以後,基本就通了。最後感謝一波阮大佬~~