0

I have a class designMain which extends design.

I have found that if I set an eventListener in design, when the event is fired, all references to this will only refer to the non extended design object. Is there a way to overcome this shortcoming of my extended class?

UPDATE - I've included an ES6 version which works as expected and shows what I am trying to accomplish - namely that this with extended classes will always refer to the extended class even with code (e.g. addEventListener) within the base class. In this case this.name should always be from the extended class.

Here is a jsFiddle

HTML

<div id="test">
    Design (click will fail)
</div>

<div id="test2">
    DesignMain (click will succeed)
</div>

javascript

design = (function() {
  function design() {
    this.name = "design";

    var _this = this;
    var e = document.getElementById("test");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  }

  design.prototype.callHello = function() {
    // I expect that this.name will be "designMain"
    console.log(this.name)
    // will fail if called from the design class eventListener
    this.hello();
  }

  return design;
})();


designMain = (function() {
  function designMain() {
    this.name = "designMain";
    this.init();
  }

  designMain.prototype.init = function() {
    this.extend();
    var _this = this;
    var e = document.getElementById("test2");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  }

  designMain.prototype.extend = function() {
    var old = new design();
    // save reference to original methods
    this._designMain = Object.create(old);
    for (var name in this._designMain) {
      if (!this[name]) {
        this[name] = this._designMain[name]
      }
    }
  }

  designMain.prototype.hello = function() {
    alert("Hello " + this.name);
  }

  return designMain;
})();


var t = new designMain();

Using ES6 - it works as expected (see fiddle)

class design {
  constructor() {
    this.name = "design";

    var _this = this;
    var e = document.getElementById("test");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  };

  callHello() {
    // should be "designMain"
    console.log(this.name)
    this.hello();
  }

  get name() {
    return this._name;
  };
  set name(name) {
    this._name = name;
  };
}


class designMain extends design {
  constructor() {
    super();
    this.name = "designMain";
    var _this = this;
    var e = document.getElementById("test2");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  };

  hello() {
    alert("Hello " + this.name);
  }

}

t = new designMain();
mseifert
  • 5,390
  • 9
  • 38
  • 100
  • I don't get it. Do you want `design` to inherit from `designMain`? If yes, why didn't you do anything to achieve that? And what is this `extend` method supposed to do? – Bergi Dec 11 '16 at 11:52
  • Your `ceate` method (which should be static, btw) is deprecated. Just use `Object.create` instead. – Bergi Dec 11 '16 at 11:53
  • @Bergi - I've updated the question with an ES6 version which behaves as expected - namely that designMain inherits extends design and all references to `this` will be designMain methods and properties. I updated my code to use Object.create, and fiddled around with static functions, but was not able to get `this` to update within code generated with the base "class". Is it possible to simulate true class inheritance without using the ES6 Class way? – mseifert Dec 11 '16 at 17:47
  • [Sure it's possible](http://stackoverflow.com/a/10898859/1048572). The problem with your original code is that it somehow conflates composition (designMain contains a design) with inheritance (design uses designMain methods) – Bergi Dec 11 '16 at 17:59
  • @Bergi - Great link, thanks. It gave me what I needed and I've posted an anwser for anyone who follows. If you want to post an answer, I'd be happy to accept it. – mseifert Dec 11 '16 at 18:16

1 Answers1

0

Thanks to Bergi and the link he posted - I have a solution. Extending / inheriting was way simpler using Object.create and I only needed to add design.call(this) to run the constructor of the base class.

designMain = (function() {
  designMain.prototype = Object.create(design.prototype);

  function designMain() {
    design.call(this)

Working solution:

design = (function() {
  function design() {
    this.name = "design";

    var _this = this;
    var e = document.getElementById("test");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  }

  design.prototype.callHello = function() {
    // will fail if called from the design class eventListener
    console.log(this.name)
    this.hello();
  }

  return design;
})();


designMain = (function() {
  designMain.prototype = Object.create(design.prototype);

  function designMain() {
    design.call(this)
    this.name = "designMain";
    this.init();
  }

  designMain.prototype.init = function() {
    var _this = this;
    var e = document.getElementById("test2");
    e.addEventListener("click", function() {
      _this.callHello();
    });
  }

  designMain.prototype.hello = function() {
    alert("Hello " + this.name);
  }

  return designMain;
})();


var t = new designMain();
mseifert
  • 5,390
  • 9
  • 38
  • 100