Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does 'this' in javascript reference to?

I'm not sure where this points in JavaScript. And I give 2 examples.

Can you help me analyze them? Thank you very much.

//exmp1
function f1()
{
  alert(this);
  function f2()
  {
    alert(this);
  }
  f2();
}
f1();

//exmp2
var jsn = 
{
  name : "b",
  func : function() // closure
  {
    alert(this); 
    return function()
    {
      return this;
    }
  }
}

alert(jsn.func()());
like image 322
slee Avatar asked Dec 07 '22 00:12

slee


1 Answers

this is different in JavaScript than it is in some other languages like C++ or Java. The value of this in your first example will always be the global object (window, on browsers). this in your second example is the jsn object for the first alert, and window for the second. This is because this is determined entirely by how a function is called, not where it's defined.

If you don't do anything special when calling the function, this is the global object. When you call a function via an object property (jsn.func()), this is set to the object the property came from. (But don't get the wrong impression, func is in no way specially tied to jsn; JavaScript doesn't have methods, just functions; details.) f1 then returns a function, which is called within the final alert; since that call is not via an object property, this is set to the global object.

Some examples:

// Simple function
function foo() {
    alert(this === window);
}
foo(); // true, within the call, `this` === `window`

// Object example, and twist at the end
var obj = {
    func: function() {
        alert(this === obj);
    },
};
obj.func();    // true, within the call, `this` === `obj`
obj["func"](); // true, within the call, `this` === `obj`

var f = obj.func; // Not calling it, just getting a reference to the function
f(); // false, within the call `this` !== `obj` (`this` === `window`)

// Creating functions on the fly, returning them, and how that has
// nothing whatsoever to do with how `this` gets set:
var obj = {
    func: function() {
        return function() {
            alert("I'm a generated function");
            alert(this === obj);
        };
     }
};
obj.func()(); // alerts the "I'm a generated function", then false; `this` !== `obj`
obj.bar = obj.func();
obj.bar();    // alerts the "I'm a generated function", then true; `this` === `obj`

There's a second way to control what this is within a function: Use the .call or .apply features of JavaScript functions:

var obj = {
    func: function() {
        alert(this === obj);
    }
};
function foo(a, b) {
    alert(this === obj); // Yes, really obj; see below
    alert(a);
    alert(b);
}
foo(1, 2);               // alerts false (`this` !== `obj`), then 1, then 2
obj.func();              // alerts true, `this` === `obj`
foo.call(obj, 3, 4);     // alerts true (`this` === `obj`), then 3, then 4
foo.apply(obj, [5, 6]);  // alerts true (`this` === `obj`), then 5, then 6

As you can see, the first argument to call or apply is the object to make this within the function call. The only difference between call and apply is how you specify arguments to pass into the target function: With call, you just supply them after the first argument; with apply, you supply them as an array.

And finally, there's a third way: The new keyword. JavaScript has the concept of constructor functions. The purpose of a constructor function is to create instances of objects initialized in a particular way. Here's an example:

function Foo(b) {
    this.bar = b;
}
var f = new Foo();

Technically, any function can be used as a constructor function. The convention is to give functions meant to be used with new names starting with a capital letter, just to reinforce that we call them in a special way.

Calling a function via new creates a new object instance and makes that object the this value within the function call. So

function Foo(b) {
    alert(this === window);
}
var f = new Foo(); // alerts false, `this` !== `window` (it points to the new object created for the call)
var f = Foo();     // alerts true, `this` === `window` because we didn't use `new`

As you can see, it's important to call a function in the correct way. If it's designed to be used with new, call it via new; if it's not, don't.

(new does more than just create a blank object; the object created has some other aspects set up in a certain way. I won't go into the details here, but I didn't want to leave you with the impression that all it did was create a new object instance.)

like image 197
T.J. Crowder Avatar answered Dec 22 '22 16:12

T.J. Crowder