The above comments are merely guessing the reason of the code failure.
Despite all the other code smells that luckily do not contribute to throwing errors, the biggest mistake within test()
(at line 30 of the code example) is to call addEventListener.call(ob, "Change", function() { changeHandler() });
.
The invocation is illegal because it is going to cheat about the bound context. It fails because the global
or window
object does not equal ob
. If one invokes e.g ob.addEventListener.call(ob, "Change", changeHandler2);
everything is perfectly fine because the context still does target the same reference.
function MyClass(name) {
var target = document.createTextNode(null);
this.addEventListener = target.addEventListener.bind(target);
this.removeEventListener = target.removeEventListener.bind(target);
this.dispatchEvent = target.dispatchEvent.bind(target);
this.MyName = name;
this.ModifyName = function(newName) {
this.MyName = newName;
this.dispatchEvent(new Event("Change"));
};
}
MyClass.prototype = EventTarget.prototype;
function changeHandler() {
console.log(`From changeHandler`);
}
function changeHandler2() {
console.log(`From changeHandler2`);
}
function test() {
var ob = new MyClass("OrgName");
ob.addEventListener("Change", changeHandler);
// allowed because the context still does target the same reference.
ob.addEventListener.call(ob, "Change", changeHandler2);
// - not allowed because it tries to cheat about the bound context, ...
// ...it fails because `global` or `window` object does not equal `ob`.
//
// //addEventListener.call(ob, "Change", function() { changeHandler() });
console.log(ob.MyName);
ob.ModifyName("UpdatedName");
console.log(ob.MyName);
}
test();
.as-console-wrapper { min-height: 100%!important; top: 0; }
Because the OP's example anyhow already makes use of EventTarget
(line 16 does state MyClass.prototype = EventTarget.prototype;
), on could switch to class
syntax and implement MyClass
in a (c)leaner way ...
class MyClass extends EventTarget {
constructor(myName) {
super();
// make it cheat proof, preserve the original `this` context.
var eventTarget = this;
this.name = myName;
this.modifyName = function(newName) {
// using the outer `eventTarget` prevents a `this` context change
// from outside via e.g. `ob.modifyName.call(obj_2, "UpdatedName_2")`
eventTarget.name = newName;
eventTarget.dispatchEvent(new Event("namechange", {
srcElement: eventTarget,
currentTarget: eventTarget,
target: eventTarget
}));
};
}
}
function changeHandler(evt) {
console.log('From changeHandler');
// console.log('From changeHandler :: evt :', evt);
}
function changeHandler_2(evt) {
console.log('From changeHandler_2');
// console.log('From changeHandler_2 :: evt :', evt);
}
function test() {
var ob = new MyClass("OrgName");
ob.addEventListener("namechange", changeHandler);
var obj_2 = { name: "OrgName_2" };
obj_2.dispatchEvent = ob.dispatchEvent.bind(obj_2);
// allowed because the context still does target the same reference.
ob.addEventListener.call(ob, "namechange", changeHandler_2);
// // throws invocation error cause it tries to cheat about the context.
// ob.addEventListener.call(obj_2, "namechange", changeHandler_2);
console.log(ob.name);
console.log(obj_2.name);
ob.modifyName("UpdatedName");
ob.modifyName.call(obj_2, "UpdatedName_2");
console.log(ob.name);
console.log(obj_2.name);
}
test();
.as-console-wrapper { min-height: 100%!important; top: 0; }