如何在Node.JS中实现继承

如何在Node.JS中实现继承,node.js,inheritance,Node.js,Inheritance,如何在Node.JS中使用“继承”?我听说原型类似于java中的接口。但是我不知道如何使用它 尽管javascript中有多种执行继承和OO的方法,但在Node.js中,您通常会使用内置函数来创建从另一个继承的构造函数 有关此主题的详细讨论,请参阅 例如: var util = require("util"); var events = require("events"); function MyOwnClass() { // ... your code. } util.inheri

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

尽管javascript中有多种执行继承和OO的方法,但在Node.js中,您通常会使用内置函数来创建从另一个继承的构造函数

有关此主题的详细讨论,请参阅

例如:

var util = require("util");
var events = require("events");

function MyOwnClass() {
    // ... your code.
}

util.inherits(MyOwnClass, events.EventEmitter);

在纯JS中创建对象构造函数:

function SubConstructor(){
    this.anotherMethod(){ alert('nothing special'); }
}

function SubConstructor.prototype = new Constructor();

var instance = new SubConstructor();

instance.public(); //alerts that private string
( 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"
它们只是与任何其他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
( 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"
关键的区别在于,原型继承来自对象,而不是构建它们的东西

一个缺点是,没有很好的方法来编写一些东西,使得像private这样的实例变量的继承成为可能

然而,gigantor的巨大优势在于,我们可以在不影响超级构造函数的情况下处理原型,甚至在构建每个对象之后更改其方法或属性。这在实践中很少在更高级别的代码中实现,因为这会导致非常混乱的API,但对于那些可能希望在一组实例之间共享不断变化的值而不只是使其全局化的隐藏类型的东西来说,这是非常方便的

我们得到这种后实例化行为的原因是,JS继承实际上是在一个查找过程中操作的,在这个过程中,任何方法调用都会沿着实例链及其构造函数原型属性运行,直到找到被调用的方法或退出为止。如果您对级联继承(这被广泛认为是一种反模式)非常疯狂,那么这实际上会变得很慢

实际上,我自己并不是专门为继承而使用prototype的,而是更喜欢通过一种更为复合的方法来构建对象,但当您需要它时,它非常方便,并且提供了许多不太明显的实用程序。例如,如果只有一个属性不同,但您不想接触原始属性,则您拥有一个对您有用的对象

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 SubConstructor(){
    this.anotherMethod(){ alert('nothing special'); }
}

function SubConstructor.prototype = new Constructor();

var instance = new SubConstructor();

instance.public(); //alerts that private string
( 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"
注意:构造函数周围的参数允许在一个位置定义和计算它,这样我就可以把它当作同一行上的一个对象

myMethod发出“undefined”警报,因为外部覆盖的方法是在构造函数的闭包之外定义的,这使内部变量变得私有。因此,您可以替换该方法,但无法访问它所做的操作

现在让我们做一些评论

( 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。关键在于构造函数本身是否定义了某些内容。注意,传递给构造函数的参数实际上也是私有实例变量,这对于重写一组默认选项非常方便

结合更多细节

在使用new调用时,实际上没有必要使用parens,除非您有必需的参数,但我倾向于将它们保留在习惯中(将它们视为触发的函数,然后将表示该触发范围的对象保留在后面是可行的),并认为它对Java开发人员的陌生程度不如
new构造函数

此外,对于任何需要参数的构造函数,我喜欢在内部添加默认值,例如:

var param = param || '';
这样,您就可以将构造函数传递到方便的方法中,比如Node的util.inherit,而不必使用未定义的值来破坏您的功能

参数也是有效的私有持久实例变量,就像构造函数中定义的任何变量一样

Oh和对象文字(用
{key:'value'}
定义的对象)可能被认为大致等同于以下内容:

var instance = new Object();
instance.key = 'value';

在Coffeescript的一点帮助下,我们可以更轻松地实现它

例如:要扩展一个类:
静态特性:
实例属性:
我只取示例代码。您可以在其官方网站上了解有关CoffeeScript的更多信息:

首先,Node.js是JavaScript。如果你在谷歌上搜索(或者在stackoverflow上搜索)“javascript继承”,你会发现已经有很多答案了。你可以交换原型或调整影响所有实例化对象的属性,但你可以交换JS中的任何东西,它们不会将你绑定到契约上,这不是我见过的做得很好或很好的事情,我开始非常讨厌契约驱动的设计。很抱歉漫长的一天充满了糟糕的Java。很好的例子。让我困惑的是,我们依赖于util来实现继承,而在定义类的时候,人们通常会这样定义继承。