……
process.inherits = removed("process.inherits() has moved to sys.inherits.");
……
新版 Nodejs 还有其他API命名的修改,inherits
只是其中的一项。显然作者Ry作修改有他自己的原因,才会有这样的决定,新版总是比旧版来的有改进,但有没有其他人建议他那样做却无从而知了:)。不过私
下判断,从语意上来说继承方法应该定义在语言核心层次的,至少在sys(System)上比在 process 的语意更为合适,更为贴切。要不然,进程
process 怎么会有继承的功能呢,感觉怪怪的,呵呵。不过话说回来,sys 必须要 require 一下才能用,而 process
却是默认的全局对象,不需要使用到
require 才能访问。
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be revritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype
* @param {function} superCtor Constructor function to inherit prototype from
*/
exports.inherits = function (ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false
}
});
};
看来 NodeJS 有点特殊,与 yui、ext
的实现不太一样。可是,究竟是什么道理令到这个继承方法与众不同呢?依据源码表述,比较关键的是,似乎在于 Object.create()
该方法之上。Object.create() 又是什么呢?要疱丁解牛,揭开谜底的答案,我们可以从“基于对象的继承”和“基于类的继承”的认识来入手。
// 定义父对象animal
var animal = new Object();
animal.age = new Number();
animal.eat = function(food){...}
// 定义子对象兔子rabbit
var rabbit = new Object();
for(var i in animal){
rabbit = animal;
}
写一个for列出animal身上的所有成员,统统复制到rabbit这样原本空的对象身上。循环过后就算达到“继承”之目的了。再提炼一下,将for写成一个通用的apply()方法,如下:
Object.apply = function(superObject, sonObject){
for(var i in superObject)
sonObject = sonObject;
}
应当指出,上面的“复制成员理念”可以是可以,并且运行无误,但大家有没有留意到,apply()主要是一个for(...){...}循环。咱们
一想到“循环语句”便很容易联想到耗时、是否会引致死循环等的问题,都是不好的问题,所以看能不能使用这个for循环,总之可以避免循环就好。——问题的
深层次就涉及到代码是否优雅的问题:使用apply()被认为是不优雅的,尤其当越来越多使用apply()的时候,结果是遍布for(...)
{...}。当然解决是否优雅最直接的方法是,JavaScript语言提供直接可以代替apply()。你们看,虽然那是如此小的问题,还是值得去修
正,看来一再提倡的,追求完美、追求极致、追求越来越好可不是空喊的一句口号。
// 定义父对象animal
var animal = new Object();
animal.age = new Number();
animal.eat = function(food){...}
var rabbit = Object.create(animal);
非常直观是吧~一个create()搞掂了~实则回头看看也是表达要封装_proto_的这么一层意义,此处顺便给出实现的方法(唠叨一下,除Mozllia,V8写法亦如此,参见v8natives.js第694行):
Object.create = function( proto) {
var obj = new Object();
obj.__proto__ = proto;
return obj;
};
当然,for的方法也等价的,
Object.create = function( proto) {
var obj = new Object();
for(var i in proto)
obj = proto;
return obj;
};
// 定义一个JS类(类在js中表现为Function)
function Foo(){
// ……构造器过程
}
var o = new Object();
o.constructor = Foo;
Foo.call(o); // <---此步就是调用Foo(),更确切地说,是调用Foo构造函数。 其作用相当于var o = new Foo();
为什么要call()呢?因为new命令调用构造器function Foo(){},最后必然会返回this当前实例对象,即: