无法在JS中获得继承的类函数

时间:2014-12-22 16:13:51

标签: javascript oop inheritance

我构建了一些基础PopupBuilder类,并希望在一些不同的用例中实现它。对于每种情况,我创建一个类扩展基类 所以:

function PopupBuilder () {
    var _this = this;

    this.buildPopup = function () {
        var popup = $('<div>', {
        id: "popup",
        class: "full-page",
        click: clickHandler});
    } //works fine

    function acceptChanges () {}
    function clickHandler (event) { // works fine 
        console.log(_this); // _this doesn't overrides by child class _this. Should it? 
        acceptChanges(event); // doesn't overrides by child class function as well
    }
}

function ToServerSender (text) {
    var _this = this;
    function acceptChanges (event) {
        // send data to server
    }
}

ToServerSender.prototype = new PopupBuilder();

var updateFile = new ToServerSender();
updateFile.buildPopup();

我创建了一个子类的实例,为什么我不能使用子类代码并覆盖/扩展基类? 我应该如何重写它将起作用的代码?

2 个答案:

答案 0 :(得分:3)

您需要记住,OOP在JavaScript中的工作方式与类式OOP大不相同。

所以让我们分解一下:

var _this = this;

当在您发布的代码末尾调用new PopupBuilder()构造函数时,会发生此分配。这里的this指的是PopupBuilder类型的对象,通过继承本质上是&#34;共享&#34;在ToServerSender的所有实例中。每个ToServerSender都没有自己的_this副本。


function acceptChanges () {}

这只是PopupBuilder构造函数中存在的函数。这不是一种方法。它不能通过在ToServerSender构造函数中定义新的来覆盖它:


console.log(_this); // _this doesn't overrides by child class _this. Should it? 

如上所述,这里的_this指的是_this的一个实例,它是在您调用PopupBuilder构造函数时创建的,它在{的所有实例之间共享{1}}。


ToServerSender

这只是acceptChanges(event); // doesn't overrides by child class function as well 构造函数中acceptChanges函数的闭包。它无法被覆盖。

<小时/> 那你能做什么?

<强> 1。使用可覆盖的方法。

您需要做的一件事是将方法分配给PopupBuilder,以便子对象可以覆盖它们:

this

在这里,我们让构造函数为function PopupBuilder () { var _this = this; this.buildPopup = function () {} //works fine this.acceptChanges = function () {} this.clickHandler = function (event) { console.log(this); this.acceptChanges(event); } } 的属性分配函数,以便它们可以通过原型链继承并根据需要覆盖:

this

<强> 2。使用function ToServerSender (text) { var _this = this; // overrides prototype's .acceptchanges this.acceptChanges = function (event) { // send data to server } } 创建子类型的原型,而不是构造函数。

使用构造函数在子类型上创建原型有点过时了。 new way to do this是使用Object.create()来创建父对象原型的副本:

Object.create

但这会留下ToServerSender.prototype = Object.create(PopupBuilder.prototype); 原型而没有在ToServerSender构造函数中初始化的所有东西。这实际上是一件好事,因为PopupBuilder构造函数正在创建一个私有变量的副本,这些变量将在现有的所有PopupBuilder之间共享,可能会造成严重破坏。

解决这个问题的方法是......

第3。从子构造函数中调用父构造函数:

ToServerSenders

这里发生的是function ToServerSender(text) { PopupBuilder.call(this); var _this = this; this.a = "hello"; //this class overrides acceptChanges from PopupBuilder this.acceptChanges = function(event) { // send data to server console.log(1); console.log(_this); } } 调用本身上的ToServerSender构造函数,以便在该构造函数内创建PopupBuilder时,它指的是_this,而非共享ToServerSender。这允许您在闭包中使用它并清除您遇到的一些问题。

所以这些是要记住的主要事项。我知道这有很多东西,但你使用的越多,它就越容易。

答案 1 :(得分:0)

您需要将功能附加到对象。

function PopupBuilder () {
    var _this = this;

    this.buildPopup = function () {} //works fine

    this.acceptChanges = function() { console.log(2);}
    this.clickHandler = function(event) { // works fine 
        console.log(_this); // _this doesn't overrides by child class _this. Should it? 
        //Look a the difference here: when you use _this.acceptChanges it prints 2 when you use this.acceptChanges() it prints 1 to the console.
        this.acceptChanges(event); // doesn't overrides by child class function as well

    }
}

function ToServerSender (text) {
    var _this = this;
    this.a = "hello";
    //this class overrides acceptChanges from PopupBuilder
    this.acceptChanges = function(event) {
        // send data to server
        console.log(1);
        console.log(_this);
    }
}

ToServerSender.prototype = new PopupBuilder();

var updateFile = new ToServerSender();
updateFile.buildPopup();

查看上面的代码,看看它是如何工作的。

PopupBuilder console.log中打印_this时,它会在该范围内使用对this的引用(包含旧acceptChanges。但在ToServerSender中范围已更改。此实例具有其他属性,并由该范围中的this对象引用。此示例显示使用对此的引用与对象之间的区别。

旁注:当使用多个对象实例时,请使用函数引用来避免内存问题。

示例

    this.clickHandler = clickHandlerPopupBuilder
    function clickHandlerPopupBuilder(event) {
        console.log(_this);
        this.acceptChanges(event);          
    }