假设我有一个javascript类Library1.B
,它从同一个库中的超类继承methodA
。
假设我想将Library1
克隆到Library2
中以制作我自己的版本,并通过略微覆盖Library1.B
继承的methodA
来改进它。天真地,我开始这样做:
/* Library 1 */
var Library1 = {};
Library1.A = function() {
console.log("A's constructor called");
};
Library1.A.prototype.methodA = function() {
console.log("methodA called with arguments", arguments);
//heavy computation
};
Library1.B = function() {
Library1.A.call(this);
//Set a few other properties exclusive to B
};
Library1.B.prototype = Object.create(Library1.A.prototype);
/* Library 2 */
var Library2 = Library1;
Library2.B.prototype.methodA = function() {
console.log("Before invoking methodA()");
Library1.B.methodA.apply(this, arguments);
console.log("After invoking methodA()");
};
var o1 = new Library1.B();
o1.methodA(1, 2, 3);
var o2 = new Library2.B();
o2.methodA(4, 5, 6);
(JSFiddle here)
上述的预期日志:
一个名为
之后
的构造函数 方法A使用参数[1,2,3]进行调用 一个名为
的构造函数 在调用methodA()之前 方法A使用参数[4,5,6]进行调用 在调用methodA()
相反,我得到了这个:
一个名为
的构造函数 在调用methodA()之前 未捕获的TypeError:无法读取属性' apply'未定义的
显然o1
,尽管是使用Library1.B
构造函数构建的对象(反过来调用Library1.A
的构造函数),但已经使用了被覆盖的对象来自methodA
的{{1}};它会在Library2
来电时崩溃,我想因为Library1.B.methodA.apply
没有自己的Library1.B
,而是从methodA
继承了它。
我写Library1.A
时的意思实际上是"查找Library1.B.methodA
的原型链,直到找到Library1.B
的定义,然后在{{1}上调用它使用这些methodA
"。
实现这个目标的正确方法是什么?
答案 0 :(得分:1)
我编辑了你的小提琴:
/* Library2 */
var Library2={};
Library2.B = function () {
console.log("L2.B's constructor starts")
Library1.B.call(this)
console.log("L2.B's constructor ends")
}
Library2.B.prototype.methodA = function() {
console.log("Before invoking methodA()");
Library1.B.prototype.methodA.apply(this, arguments); //ADDED "prototype"
console.log("After invoking methodA()");
};
现在Library2与1无关,我们从头开始编写它的成员。另一个区别在于你对方法A的超级调用:你正在寻找L1.B中或上面的方法,这是一个构造函数,它的under-under-proto是Function。虽然构造函数的原型(与原型下不同)是一个空对象,其底层原型是构造函数L1.A的原型,它是methodA所在的位置。因此,申请授权从来没有任何问题。您只是在构造函数中查找而不是原型链下的任何对象。
现在还有什么比这更简单? :^ @