JS继承学习笔记1

最近又看了一下Douglas Crockford的经典文章Classical Inheritance in JavaScript 和玉伯写的 Crockford uber方法中的陷阱

Douglas写的uber方法在处理“断层”继承时会有问题,并且继承没有恢复constructor。

玉伯改写的方法,增加了superclass属性来记录父类构造器,继承时还原了constructor,并且利用hasOwnProperty跳过断层,并且迭代时再次判断了f 和 this[name] 是否相等。

玉伯的方法在测试“断层”时,能跳过断层实现继承,但是结果还是有问题。

理论上,最后两行应该都输出  D1,D2,D5。但实际输出结果是:

println(d6.getName()); // => D1,D2,D5   
println(d6.uber('getName')); // => D1,D2 

再测试下没有断层的情况,能实现继承:

function D1() {}   
D1.prototype.getName = function() { return 'D1' }; // @4   
  
function D2() {}   
D2.inherits(D1);   
D2.prototype.getName = function () { return this.uber('getName') + ',D2'; }; // @5   
var d2 = new D2();
println(d2.getName());   
println(d2.uber('getName'));  

function D3() {}   
D3.inherits(D2);  
D3.prototype.getName = function () { return this.uber('getName') + ',D2'; }; 
var d3 = new D3();
println(d3.getName());   
println(d3.uber('getName'));     

function D4() {}   
D4.inherits(D3);  
D4.prototype.getName = function () { return this.uber('getName') + ',D2'; }; 
var d4 = new D4();
println(d4.getName());   
println(d4.uber('getName')); 

输出:
D1,D2
D1
D1,D2,D2
D1,D2
D1,D2,D2,D2
D1,D2,D2

 

但是当子类的方法跟父类的方法一模一样时,还是会有继承问题。将上面的测试代码稍微改一下,去掉D3.prototype.getName的赋值。

function D1() {}   
D1.prototype.getName = function() { return 'D1' }; // @4   
  
function D2() {}   
D2.inherits(D1);   
D2.prototype.getName = function () { return this.uber('getName') + ',D2'; }; // @5   
var d2 = new D2();
println(d2.getName());   
println(d2.uber('getName'));  

function D3() {}   
D3.inherits(D2);   
var d3 = new D3();
println(d3.getName());   
println(d3.uber('getName'));     

function D4() {}   
D4.inherits(D3);  
D4.prototype.getName = function () { return this.uber('getName') + ',D2'; }; 
var d4 = new D4();
println(d4.getName());   
println(d4.uber('getName'));  


理论上,如果成功继承,应该输出:

D1,D2
D1
D1,D2
D1
D1,D2,D2
D1,D2

 

测试结果输出:

D1,D2
D1
D1,D2
D1
D1,D2,D2,D2
D1,D2,D2

 

D4和D3的继承被多隔出一层。

当把最开始D1-D6的例子,将D1-D6全部输出时,发现一个更有意思的现象:

function D1() {}   
D1.prototype.getName = function() { return 'D1' }; // @4   
  
function D2() {}   
D2.inherits(D1);   
D2.prototype.getName = function () { return this.uber('getName') + ',D2'; }; // @5   
var d2 = new D2();
println(d2.getName());   
println(d2.uber('getName'));  

function D3() {}   
D3.inherits(D2);  
var d3 = new D3();
println(d3.getName());   
println(d3.uber('getName'));     

function D4() {}   
D4.inherits(D3);  
var d4 = new D4();
println(d4.getName());   
println(d4.uber('getName'));    

function D5() {}   
D5.inherits(D4);   
D5.prototype.getName = function () { return this.uber('getName') + ',D5'; }; // @6   
var d5 = new D5();
println(d5.getName());   
println(d5.uber('getName'));  


function D6() {}   
D6.inherits(D5);   

var d6 = new D6();   
println(d6.getName());   
println(d6.uber('getName'));

输出:

D1,D2
D1
D1,D2
D1
D1,D2
D1
D1,D2,D2,D5
D1,D2,D2
D1,D2,D5
D1,D2

这里,D6继承D5,D5继承D4,结果D5和D4之间多了一层,D6输出的反而比D5短。

 


暂时没有想到解决这个问题,不过,在JS中实现OO的对象继承真的好难。

 

 

 

 

posted @ 2013-08-29 21:34  sunnyfish  阅读(224)  评论(0)    收藏  举报