Can you explain me why does the second call of fn
gives an error? The code is below.
function Test(n) {
this.test = n;
var bob = function (n) {
this.test = n;
};
this.fn = function (n) {
bob(n);
console.log(this.test);
};
}
var test = new Test(5);
test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function
Here's a JSfiddle that reproduces the error http://jsfiddle.net/KjkQ2/
Your bob
function is called from the global scope. Thefore, this.test
is pointing at a global variable named test
which is overwriting the variable you created. If you run console.log(window.test)
, you'll what's happening.
For your code to behave as intended, you would need one of the following
function Test(n) {
this.test = n;
// If a function needs 'this' it should be attached to 'this'
this.bob = function (n) {
this.test = n;
};
this.fn = function (n) {
// and called with this.functionName
this.bob(n);
console.log(this.test);
};
}
OR
function Test(n) {
this.test = n;
var bob = function (n) {
this.test = n;
};
this.fn = function (n) {
// Make sure you call bob with the right 'this'
bob.call(this, n);
console.log(this.test);
};
}
OR closure based objects
// Just use closures instead of relying on this
function Test(n) {
var test = n;
var bob = function (n) {
test = n;
};
this.fn = function (n) {
bob(n);
console.log(test);
};
}
When calling bob(n)
within .fn
, it is called within the global context
(window
in a browser). Now, you're setting window.test = n;
which basically overwrites your function test
object you created earlier.
If we you write this more explicit, it becomes more obvious:
// in the global scope, `test` gets written to the `global object`
// window.test = new Test(5);
var test = new Test(5);
test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function
You can "workaround" this issue by calling bob()
with an explicit context, using .call()
for instance:
this.fn = function (n) {
bob.call(this,n);
console.log(this.test);
};
The root of evil here is, that the value of this
is dynamically assigned during run-time. Don't get me wrong, its actually a great feature of ECMAscript - it's just the problem for you here. When you call a function, "just like that", this
will always reference the global object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With