Javascript 继承覆盖

Javascript Inheritance Overriding

网络上有很多关于 Javascript 覆盖的令人困惑的文献。但是,我还没有找到任何一个可以满足我的需要。我正在尝试启用继承和方法覆盖,但是是以一种特定的方式。

想象一下:

var A = function(amount) {
    this.amount = amount;
    var _this = this;

    this.method1 = function() {
        some_asynchronous_function(this.amount, function(result) {
            _this.method2(result);
        });
    };
    //The function we want to override!
    this.method2 = function(result) {
        do_stuff(result);
    };
};

var B = function(amount) {
    this.method2 = function(result) {
        do_different_stuff(result);
    };
    A.call(this, amount);
};
B.prototype = Object.create(A.prototype);

我的目标是能够保留 A class 中的所有内容,但 this.method2 除外。但是,当我在我的代码中实例化 B 并调用 B.method1 时,它会从 A 执行 method2。有没有办法将我保留的内容与 Javascript 混合搭配?

这证明了您问题的本质:

var A = function() {
    this.m1 = function(){ console.log('hi from m1 from A');  };
    this.m2 = function(){ console.log('hi from m2 from A');  };
};

var B = function() {
    this.m2 = function(){ console.log('hi from m2 from B');  };
    A.call(this); //try swapping this with the previous line
};
(new B()).m2();

您在构造函数中将方法定义为实例属性。 由于您在 m2 定义之后创建 A 构造函数 运行,并且构造函数有自己的 m2 定义,因此它将覆盖它之前的定义。

此处没有有效的原型。

不过,您应该为此使用原型。 如果您将这些方法定义为实例属性,它们将分别为每个实例重新定义 new

如果将这些方法定义移至原型,代码将得到重用:

var A = function() {

};
A.prototype.m1 = function(){ console.log('hi from m1 from A');  };
A.prototype.m2 = function(){ console.log('hi from m2 from A');  };

var B = function() {
    A.call(this); 
};
B.prototype = Object.create(A.prototype);
B.prototype.m2 = function(){ console.log('hi from m2 from B');  };

(new B()).m2();
(new B()).m1();

之后,原型继承真的很简单:

  • 实例methods/attributes覆盖它们是原型祖先
  • 在原型中找到的属性会覆盖在原型的原型(等等)中找到的属性
  • 所有写入都转到实例(instance.attr = 42 不会覆盖原型中的属性,而是会在 instance 上创建一个新属性 属性)

你需要原型继承,像这样:

var A = function (){
    this.init.apply(this, arguments);
};
A.prototype = Object.create(Object.prototype, {
    amount: null,
    init: function (amount){
        this.amount = amount;
    },
    method1: function() {
        some_asynchronous_function(this.amount, this.method2.bind(this));
    },
    method2: function(result) {
        do_stuff(result);
    };
});

var B = function (){
    this.init.apply(this, arguments);
};
B.prototype = Object.create(A.prototype, {
    method2: function(result) {
        do_different_stuff(result);
    }
});

注意:Object.create 并非在每个环境中都有第二个参数。

大部分js框架都或多或少的支持继承,选一个吧。如果你想创建自己的,那么我已经实现了一个扩展功能here,也许你可以使用一些想法。

如果您的 A class 有太多行(例如超过 50 条)或方法(超过 10 条)或它违反了 class 方法 2 的替代方法=12=]。但我想这些东西对你来说并不重要。