Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
125 views
in Technique[技术] by (71.8m points)

javascript - Unable to access the object using `this`. `this` points to `window` object

I have this Javascript constructor-

function TestEngine() {
    this.id='Foo';
}

TestEngine.prototype.fooBar = function() {
    this.id='bar';
    return true;
}

TestEngine.prototype.start = function() {
    this.fooBar();
}

TestEngine.prototype.startMethod = function() {
    inter = setInterval(this.start, 200);
}

var test = new TestEngine();
test.startMethod();

Gives me this error -

Uncaught TypeError: Object [object global] has no method 'fooBar' 

I tried console.log and found out that when I call this.start from within setInterval, this points to the window object. Why is this so?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The this pointer can point to one of many things depending upon the context:

  1. In constructor functions (function calls preceded by new) this points to the newly created instance of the constructor.
  2. When a function is called as a method of an object (e.g. obj.funct()) then the this pointer inside the function points to the object.
  3. You can explicitly set what this points to by using call, apply or bind.
  4. If none of the above then the this pointer points to the global object by default. In browsers this is the window object.

In your case you're calling this.start inside setInterval. Now consider this dummy implementation of setInterval:

function setInterval(funct, delay) {
    // native code
}

It's important to understand that start is not being called as this.start. It's being called as funct. It's like doing something like this:

var funct = this.start;
funct();

Now both these functions would normally execute the same, but there's one tiny problem - the this pointer points to the global object in the second case while it points to the current this in the first.

An important distinction to make is that we're talking about the this pointer inside start. Consider:

this.start();           // this inside start points to this
var funct = this.start;
funct();                // this inside funct (start) point to window

This is not a bug. This is the way JavaScript works. When you call a function as a method of an object (see my second point above) the this pointer inside the function points to that object.

In the second case since funct is not being called as a method of an object the fourth rule is applied by default. Hence this points to window.

You can solve this problem by binding start to the current this pointer and then passing it to setInterval as follows:

setInterval(this.start.bind(this), 200);

That's it. Hope this explanation helped you understand a little bit more about the awesomeness of JavaScript.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...