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的对象继承真的好难。

浙公网安备 33010602011771号