Reputation: 13342
Why this works when I launch from nodejs:
var a = function (name) {
return "Hello, " + name.toUpperCase();
};
var result = a("bob");
console.log(result)
But this:
var A = (function () {
function A(msg) {
this.msg = " ";
this.msg = msg;
}
A.prototype.hello = function (name) {
return "Hello, " + name.toUpperCase();
};
A.prototype.helloToBob = function (fn) {
return fn.apply("Bob");
};
return A;
})();
var test = new A("some message");
var msg = test.hello("Bob1");
var msg2 = test.helloToBob(test.hello);
console.log(msg);
fails with:
return "Hello, " + name.toUpperCase(); ^ TypeError: Cannot call method 'toUpperCase' of undefined
?
That JS code generated/compiled from TypeScript code.(compiled with no errors)
Upvotes: 1
Views: 2810
Reputation: 707158
The issue is in this line of code.
return fn.apply("Bob");
The are a couple issues here.
The first argument to .apply(obj, arrayOfArguments)
needs to be the object that you want the this
pointer set to during the method call.
The second argument for .apply()
is an array of arguments, not a single argument.
Here's one possible solution where you use this
as the object and switch to fn.call()
because fn.apply()
takes an array of arguments, but you just have a single argument.
Change this:
return fn.apply("Bob");
to this:
return fn.call(this, "Bob");
And, all the code together:
var A = (function () {
function A(msg) {
this.msg = " ";
this.msg = msg;
}
A.prototype.hello = function (name) {
return "Hello, " + name.toUpperCase();
};
A.prototype.helloToBob = function (fn) {
return fn.call(this, "Bob");
};
return A;
})();
var test = new A("some message");
var msg = test.hello("Bob1");
var msg2 = test.helloToBob(test.hello);
console.log(msg);
FYI, there are other solutions. You could also do this:
var A = (function () {
function A(msg) {
this.msg = " ";
this.msg = msg;
}
A.prototype.hello = function (name) {
return "Hello, " + name.toUpperCase();
};
A.prototype.helloToBob = function (fn) {
return fn("Bob");
};
return A;
})();
var test = new A("some message");
var msg = test.hello("Bob1");
var msg2 = test.helloToBob(test.hello.bind(test));
console.log(msg);
Upvotes: 2
Reputation: 1950
Because the first argument you should pass to apply() is the context object, it is NOT the first argument of the function itself. Do check the docs.
Since helloToBob() is a class method of A, I assume, you intend to call fn in the context of the current object, is this what you are after:
A.prototype.helloToBob = function (fn) {
return fn.apply(this, ["Bob"]);
};
// or, since you have a single static argument, use function.call instead:
A.prototype.helloToBob = function (fn) {
return fn.call(this, "Bob");
};
Upvotes: 2