我们如何在Node.JS中使用'继承'?我听说原型类似于java中的接口。但我不知道如何使用它!
答案 0 :(得分:6)
尽管在javascript中有各种方法可以执行继承和OO,但在Node.js中,您通常会使用内置的util.inherits函数来创建一个继承自另一个的构造函数。
有关此主题的详细讨论,请参阅http://book.mixu.net/ch6.html。
例如:
var util = require("util");
var events = require("events");
function MyOwnClass() {
// ... your code.
}
util.inherits(MyOwnClass, events.EventEmitter);
答案 1 :(得分:4)
在纯JS中创建对象构造函数:
它们只是像任何其他JS函数一样的函数,但是使用new关键字调用。
function Constructor(){ //constructors are typically capitalized
this.public = function(){ alert(private); }
var private = "Untouchable outside of this func scope.";
}
Constructor.static = function(){ alert('Callable as "Constructor.static()"'); }
var instance = new Constructor();
<强>继承:强>
function SubConstructor(){
this.anotherMethod(){ alert('nothing special'); }
}
function SubConstructor.prototype = new Constructor();
var instance = new SubConstructor();
instance.public(); //alerts that private string
关键的区别在于原型继承来自对象,而不是构建它们的东西。
一个缺点是没有很好的方法来编写使私有的实例变量继承的东西。
然而,巨大的巨型优势是,我们可以在不影响超级构造函数的情况下搞乱原型,甚至在构建之后为每个对象更改方法或属性。这在高级代码的实践中很少发生,因为它会产生一个非常令人困惑的API,但它对于引擎盖类型的东西很方便,你可能希望在一组实例中共享一个不断变化的值,而不仅仅是制作它是全球性的。我们获得此实例化后行为的原因是因为JS继承实际上在查找过程中运行,其中任何方法调用都会运行实例链及其构造函数原型属性,直到找到调用或退出的方法。如果你对级联继承感到绝对疯狂(这被广泛认为是一种反模式),这实际上会变慢。
我实际上并没有专门针对inheritacne打造原型,而是更喜欢通过更复合的方法来构建对象,但是当你需要它时它非常方便并且提供了很多不太明显的实用性。例如,当您有一个对您有用的对象时,如果只有一个属性不同,但您不想触及原始属性。
var originInstance = {
originValue:'only on origin',
theOneProperty:'that would make this old object useful if it were different'
}
function Pseudoclone(){
this.theOneProperty = "which is now this value";
}
Pseudoclone.prototype = originInstance;
var newInstance = new Psuedoclone();
//accesses originInstance.originValue but its own theOneProperty
还有更多的现代便捷方法,比如Object.create,但只有函数构造函数可以让你选择封装私有/实例变量,所以我倾向于支持它们,因为10次中不需要封装的9次只会是对象文字
覆盖和调用对象顺序:
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
instance.myMethod = function(){ alert(private); }
instance.myMethod();//"undefined"
注意:构造函数周围的parens允许在一个位置定义和计算它,所以我可以将它视为同一行上的一个对象。
myMethod警告“未定义”,因为外部覆盖的方法是在构造函数的闭包之外定义的,这有效地使内部变量像私有一样。因此,您可以替换该方法,但您无法访问它所执行的操作。
现在让我们做一些评论。
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"public referencing private"
和...
( function Constructor(){
var private = "public referencing private";
//this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"prototype"
请注意,出于同样的原因,原型方法也无法访问该内部私有var。这是关于是否在构造函数本身中定义了某些东西。请注意,传递给构造函数的params也将实际上是私有实例变量,这可以方便地执行诸如覆盖一组默认选项之类的事情。
结合更多详情
实际上没有必要在使用new调用时使用parens,除非你有必要的参数但是我倾向于让它们不习惯(它可以将它们看作是触发的函数,然后留下一个表示该范围的对象)后面开火)并认为它对Java开发人员的影响不如new Constructor;
此外,对于任何需要params的构造函数,我喜欢在内部添加默认值,例如:
var param = param || '';
这样你就可以将构造函数传递给方便的方法,比如Node的util.inherit,而没有未定义的值会破坏你的东西。
Params也是有效的私有持久化实例变量,就像构造函数中定义的任何var一样。
哦和对象文字(用{ key:'value' }
定义的对象)可能最好被认为大致相当于:
var instance = new Object();
instance.key = 'value';
答案 2 :(得分:0)
在Coffeescript的帮助下,我们可以更容易地实现它。
class Animal
constructor: (@name) ->
alive: ->
false
class Parrot extends Animal
constructor: ->
super("Parrot")
dead: ->
not @alive()
class Animal
@find: (name) ->
Animal.find("Parrot")
class Animal
price: 5
sell: (customer) ->
animal = new Animal
animal.sell(new Customer)
我只是采用示例代码Classes in CoffeeScript。您可以在其官方网站上了解有关CoffeeScript的更多信息:http://coffeescript.org/