您的位置:首页 > Web前端 > JavaScript

javascript实现面向对象的继承

2012-02-29 23:23 621 查看
作者:Yan

Douglas Crockford 的方案:

//Crockford's approach adds the 'inherits' method
//to all functions, as well as a per-class method
//called 'uber' that allows you to make super calls.
Function.prototype.inherits = function(parent) {
var d = 0, p = (this.prototype = new parent());

this.prototype.uber = function(name) {
var f, r, t = d, v = parent.prototype;
if (t) {
while (t) {
v = v.constructor.prototype;
t -= 1;
}
f = v[name];
} else {
f = p[name];
if (f == this[name]) {
f = v[name];
}
}
d += 1;
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
d -= 1;
return r;
};
};
function BaseClass() { }
BaseClass.prototype.getName = function() {
return "BaseClass(" + this.getId() + ")";
}

BaseClass.prototype.getId = function() {
return 1;
}

function SubClass() {}
SubClass.inherits(BaseClass);
SubClass.prototype.getName = function() {
//Looks pretty clean and it calls
//the getName() method of BaseClass
return "SubClass(" + this.getId() + ") extends " +
this.uber("getName");
}

SubClass.prototype.getId = function() {
return 2;
}

function TopClass() {}
TopClass.inherits(SubClass);
TopClass.prototype.getName = function() {
//Looks pretty clean and it calls
//the getName() method of SubClass
return "TopClass(" + this.getId() + ") extends " +
this.uber("getName");
}

TopClass.prototype.getId = function() {
//Ok, so this.getId() should always
//return the result of calling getId()
//on SubClass, which is 2. So does it?
return this.uber("getId");
}

//Alerts "TopClass(2) extends SubClass(1) extends BaseClass(1)"
//Hmm... this.getId() didn't always return 2.
//What happened?
alert(new TopClass().getName());


Josh Gertzen 的方案,他指出了前面方案存在的问题,并给出他自己的方案:

//Defines the top level Class
function Class() { }
Class.prototype.construct = function() {};
Class.__asMethod__ = function(func, superClass) {
return function() {
var currentSuperClass = this.$;
this.$ = superClass;
var ret = func.apply(this, arguments);
this.$ = currentSuperClass;
return ret;
};
};

Class.extend = function(def) {
var classDef = function() {
if (arguments[0] !== Class) { this.construct.apply(this, arguments); }
};

var proto = new this(Class);
var superClass = this.prototype;

for (var n in def) {
var item = def
;

if (item instanceof Function) {
item = Class.__asMethod__(item, superClass);
}

proto
= item;
}

proto.$ = superClass;
classDef.prototype = proto;

//Give this new class the same static extend method
classDef.extend = this.extend;
return classDef;
};

//Hey, this class definition approach
//looks much cleaner than then others.
var BaseClass = Class.extend({
construct: function() { /* optional constructor method */ },

getName: function() {
return "BaseClass(" + this.getId() + ")";
},

getId: function() {
return 1;
}
});

var SubClass = BaseClass.extend({
getName: function() {
//Calls the getName() method of BaseClass
return "SubClass(" + this.getId() + ") extends " +
this.$.getName.call(this);
},

getId: function() {
return 2;
}
});

var TopClass = SubClass.extend({
getName: function() {
//Calls the getName() method of SubClass
return "TopClass(" + this.getId() + ") extends " +
this.$.getName.call(this);
},

getId: function() {
//Much better, this.getId() always
//returns the result of calling getId()
//on SubClass, which is 2.
return this.$.getId.call(this);
}
});

//Alerts "TopClass(2) extends SubClass(2) extends BaseClass(2)"
//Everything looks good!
alert(new TopClass().getName());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: