I am trying to learn more advanced approaches to inheritance in Javascript, and can’t figure out why my inherited object is loosing it’s “this” keyword binding in the example code below from Eloquent Javascript.
I’ve tried calling the take() function for example by using:
lantern.take(); // alerts you can not lift
Item.take.call(lantern, "the brass lantern"); // alerts you can not lift
lantern.take.call(this, "the brass lantern"); // alerts you can not lift
Neither of these binds this.name to lantern though? What am I missing/not understanding in my approach to calling the methods defined in my objects prototype? Thank you.
function forEachIn(object, action) {
for (var property in object) {
if (object.hasOwnProperty(property))
action(property, object[property]);
}
}
function clone(object) {
function OneShotConstructor(){}
OneShotConstructor.prototype = object;
return new OneShotConstructor();
}
Object.prototype.create = function() {
var object = clone(this);
if (typeof object.construct == "function")
object.construct.apply(object, arguments);
return object;
};
Object.prototype.extend = function(properties) {
var result = clone(this);
forEachIn(properties, function(name, value) {
result[name] = value;
});
return result;
};
var Item = {
construct: function(name) {
this.name = name;
},
inspect: function() {
alert("it is ", this.name, ".");
},
kick: function() {
alert("klunk!");
},
take: function() {
alert("you can not lift ", this.name, ".");
}
};
var lantern = Item.create("the brass lantern");
lantern.kick(); // alerts klunk
Unlike
console.log,alerttakes only one argument. You’d need to concat the strings:With that, both
lantern.take();andItem.take.call(lantern);– which are equivalent – will alert “you can not lift the brass lantern.”, while your third example depends on the value of thethiskeyword in the current execution. Btw, yourtakefunction does not take an argument.