JavaScript的语言特性 — 继承

前端技术 everyinch 1148℃ 0评论

JavaScript对象的创建与继承使用了一套特别的模式,称为原型式继承(prototypal inheritance)。这种方法的原理是,对象的构造函数可以从其它对象中继承方法,它创建出一个原型对象后,所有其他的新对象都可以基于这个原型对象来创建。这种继承方式之所以难以掌握,是因为原型本身并不会从其它原型或者构造函数中继承属性,而属性都是从实际对象那里继承过来的。

// 为 Person 对象创建一个构造函数
function Person( name ) {
    this.name = name;
}

// 为 Person 对象添加一个新方法
Person.prototype.getName = function() {
    return this.name;
};

// 创建一个新的 User 对象的构造函数
function User( name, password ) {
    this.name = name;
    this.password = password;
};

// User 对象继承所有 Person 对象的方法
User.prototype = new Person();

// 在 User 对象中添加一个新方法
User.prototype.getPassword = function() {
    return this.password;
};

例子当中最重要的一行是 User.prototype = new Person()。仔细分析一下它的含义:User是对 User 构造函数的引用。new Person() 使用了Person的构造函数创建了一个新的Person对象,然后把User构造函数的原型置为这个操作的结果。也就是说,每当 new User() 时,得到的新User对象都会带有Person对象所有的方法,如同操作 new Person() 得到的一样。

JavaScript大师Douglas Crockford实现了一套JavaScript类式继承的方法,每个函数分别实现了一种形式的继承:继承自单一函数、从单一父对象继承所有内容,以及从多个父对象继承独立的方法。

// 辅助函数,可以将新函数绑定到对象的 prototype 上
Function.prototype.method = function(name, func) {
this.prototype[name] = func;
return this;
};

// 相对复杂的函数。可以从其它对象继承函数
Function.method(‘inherits’, function(parent) {
// 记录所在父层次的级数
var depth = 0;

// 继承父对象的方法
var proto = this.prototype = new parent();

// 创建一个新的名为 ‘uber’ 的特权函数
// 调用它时会执行所有在继承时被重写的函数
this.method(‘uber’, function uber(name) {

var func; // 要执行的函数
var ret; // 函数的返回值
var v = parent.prototype; // 父对象的 prototype

// 如果已经在某个 ‘uber’ 函数之内
if (depth) {
// 上溯必要的 depth,已找到原始的 prototype
for ( var i = d; i > 0; i += 1 ) {
v = v.constructor.prototype;
}

// 从该 prototype 中获得函数
func = v[name];

// 否则这就是 ’uber’ 函数的第一次调用
} else {
// 从 prototype 获得要执行的函数
func = proto[name];

// 如果此函数 prototype 属于当前的 prototype
if ( func == this[name] ) {
// 则改为调用父对象的 prototype
func = v[name];
}
}

// 记录在继承堆栈中所在位置的级数
depth += 1;

// 使用除第一个以外所有的 arguments 调用此函数
// (因为第一个参数是执行的函数名)
ret = func.apply(this, Array.prototype.slice.apply(arguments, [1]));

// 恢复继承堆栈
depth -= 1;

// 返回执行过的函数的返回值
return ret;
});

return this;
});

// 只继承父对象特定函数的函数
// 而不是使用 new parent() 继承所有的函数
Function.method(‘swiss’, function(parent) {
// 遍历所有要继承的方法
for (var i = 1; i < arguments.length; i += 1) { // 需要导入的函数名 var name = arguments[i]; // 将此方法导入 this 对象的 prototype 中 this.prototype[name] = parent.prototype[name]; } return this; }); [/code] Function.prototype.method:把函数与构造函数的原型关联起来 Function.prototype.inherits:实现简单的单对象继承 Function.prototype.swiss:这是 .method 的增强版本,用于从单一父对象获取多个函数 利用这些函数重写一下第一个例子中的继承方法: [code lang="js"] // 为 Person 对象创建一个构造函数 function Person( name ) { this.name = name; } // 给 Person 对象添加一个新的方法 Person.method( 'getName', function(){ return name; }); // 创建一个新的 User 对象构造函数 function User( name, password ) { this.name = name; this.password = password; }; // 从 Person 对象继承所有方法 User.inherits( Person ); // 给 User 对象添加一个新的方法 User.method( 'getPassword', function(){ return this.password; }); // 覆盖 Person 对象创建的 getName 方法 // 但通过 uber 函数来调用原有方法 User.method( 'getName', function(){ return "My name is: " + this.uber('getName'); }); [/code] js8



转载请注明:陈童的博客 » JavaScript的语言特性 — 继承

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

无觅相关文章插件,快速提升流量