2012-12-30 65 views
0

對於那些不熟悉,替代繼承如下所示:爲什麼「替代」繼承關閉停止工作?

var Surrogate = function() {} 

var extend = function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
} 

var Animal = function (name) { 
    this.name = name; 
}; 

Animal.prototype.speak = function() { 
    return this.getSound() + ' ' + this.name; 
}; 

Animal.prototype.getSound = function() { 
    // Abstract 
}; 

var Cat = function (name) { 
    Animal.call(this, name); 
}; 

extend(Animal, Cat); 

Cat.prototype.getSound = function() { 
    return 'Meow'; 
}; 

var kitty = new Cat('Maru'); 
console.log(kitty.speak()); // Logs "Meow Maru" 
console.log(kitty instanceof Animal); // Logs true 
console.log(kitty instanceof Cat); // Logs true 
console.log(kitty.constructor == Cat); // Logs true 

基本上建立從Animal繼承的構造函數中,我們創建另一個構造函數(在這種情況下,Cat),調用Animal構造函數使用this的適當值,然後使用extend函數將Cat的原型設置爲沒有name屬性的Animal的「實例」。考慮使用extend(Animal, Cat)Cat.prototype = new Animal()相同,除了Cat.prototype.name未定義。

以上工作完美,我稍後有一個側面問題。

我想採取一個新的水平,並隱藏Surrogate封閉裏面,所以我改變了Surrogateextend的聲明看起來像這樣:

var extend = (function() { 
    var Surrogate = function() {}; 
    return function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
    }; 
}); 

現在,當我運行該腳本失敗上第一個日誌聲明:

TypeError: Object [object Object] has no method 'speak' 

但是,創建另一個文件extend.js具有以下內容:

var Surrogate = function() {}; 

module.exports = function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
} 

並將主腳本中extend的聲明更改爲var extend = require('./extend');作品,並且Surrogate按預期隱藏。

對於主要問題:據我所知,節點和其他CommonJS系統只是將模塊封裝在閉包函數中,就像我最初試圖做的那樣。爲什麼模塊版本可以工作,但是我的版本與閉包不兼容?

對於上面提到的側面問題:我很驚訝Sub.prototype.constructor = Sub。我認爲它應該是Sub.prototype.constructor = Base,但導致最後的日誌記錄語句記錄爲false。我想我已經爲自己回答了這個問題,但我認爲constructor是構建對象上的一個屬性,而不是原型。這是否是另一種方式?

UPDATE

我只是試圖與使用一種稱爲extend定義模塊AMD如下:

define(function() { 
    var Surrogate = function() {}; 

    return function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
    }; 
}); 

它完美的罰款。我覺得我在這裏忽略了一件極其簡單的事......爲什麼在模塊系統中工作正常,而不是在普通的關閉中工作?我測試了node.js,Chrome和Firefox中的所有版本(純文本,閉包和模塊)。

回答

1
var extend = (function() { 
    var Surrogate = function() {}; 
    return function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
    }; 
}); 

應該

var extend = (function() { 
    var Surrogate = function() {}; 
    return function (Base, Sub) { 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
    }; 
})(); 

(我剛剛追加()給它執行的功能。)

,或者如果你要防範的是代孕可能會損壞(somethign威力亂用其構造函數的可能性 - 使得它做什麼):

var extend = function (Base, Sub) { 
    var Surrogate = function() {}; 
    Surrogate.prototype = Base.prototype; 
    Sub.prototype = new Surrogate(); 
    Sub.prototype.constructor = Sub; 
}; 
+0

沒錯。返回一個函數返回一個函數... – ErikE

+0

ALBHALBHAFHLASHD。我不能相信我錯過了那些parens ...... – user1937128

+0

雅,它看起來像你甚至有可能在一個點上:p – goat