如何在Node.JS中实现继承

时间:2013-06-11 08:33:08

标签: node.js inheritance

我们如何在Node.JS中使用'继承'?我听说原型类似于java中的接口。但我不知道如何使用它!

3 个答案:

答案 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/