this keyword is window object within a constructor

2019-06-17 03:19发布

Ok, so I thought I understood this (no pun intended), but apparently not.

var Constructor = function () {
    var internalFunction = function () {
        return this === window;
    };
    this.myMethod = function () {
        alert(internalFunction());
    };
};
var myObj = new Constructor();
myObj.myMethod();

This alerts true. Why can't the internal function see this as the object? Instead I have to use alert(internalFunction.call(this)); in myMethod.

Edit: I was looking for an explanation as to why this is assigned in that way, not workarounds such as var self = this;, etc. Sorry if I didn't make that clear.

4条回答
Anthone
2楼-- · 2019-06-17 03:47

this is not bound until the function is called and is dependent on how the function is called. You could think of it as an extra parameter implicitly passed to the function.

In this case, the problem is that you're calling internalFunction using internalFunction(). The this value is set either by calling a function as a method (as in foo.bar() or foo["bar"]()) or by setting this explictly via call() or apply(). Your call is doing neither so this reverts to the global object.

The simplest way to achieve what you want in this case while keeping internalFunction private is to store a reference to this inside the constructor function:

var Constructor = function() {
    var thisObj = this;

    var internalFunction = function () {
        return thisObj === window;
    };

    thisObj.myMethod = function () {
        alert(internalFunction());
    };
}
查看更多
走好不送
3楼-- · 2019-06-17 03:48

Because of functional scoping rules, this is reassigned inside each function... I would store a copy of your object as self and use it accordingly...

var Constructor = function () {

    var self = this;

    var internalFunction = function () {
        return self === window;
    };
    this.myMethod = function () {
        alert(internalFunction());
    };
};
var myObj = new Constructor();
myObj.myMethod();

Should give you the output you expect.

SIDENOTE

This is a fairly precarious practice that javascript has created, mainly because if you forget the new keyword when using Constructor, you will get this referring to the window (god) object so you'll be attaching myMethod to the window without warning.

查看更多
SAY GOODBYE
4楼-- · 2019-06-17 03:56

There are five ways to call a function in JavaScript. The value of this depends on which you choose:

  1. Global function call (e.g. myFunction()). No explicit value for this is given. The value of this will be the default object (window in a browser).
  2. Method call (e.g. obj.myFunction()). The value of this is the object on which the method was invoked (obj in this case).
  3. Using the call method (e.g. myFunction.call(obj)). The value of this is provided explicitly (in this case obj).
  4. Using the apply method (e.g. myFunction.apply(obj)). The value of this is provided explicitly (in this case obj).
  5. Constructor function (e.g. new MyFunction()). The value of this is a newly-created object provided by the runtime.

Each of the five is explained in more detail here:

查看更多
Juvenile、少年°
5楼-- · 2019-06-17 04:06

Its a scope issue try something like:

var Constructor = function () {
    var $this = this;
    var internalFunction = function () {
        return $this === window;
    };
    this.myMethod = function () {
        alert(internalFunction());
    };
};
var myObj = new Constructor();
myObj.myMethod();
查看更多
登录 后发表回答