views:

272

answers:

6

I'm just curious to know how jQuery is able to hijack the 'this' keyword in Javascript. From the book I'm reading: "Javascript the Definitive Guide" it states that "this" is a keyword and you cannot alter it like you can with an identifier.

Now, say you are in your own object constructor and you make a call to some jQuery code, how is it able to hijack this from you?

function MyObject(){
    // At this point "this" is referring to this object
    $("div").each(function(){
        // Now this refers to the currently matched div
    });
}

My only guess would be that since you are providing a callback to the jQuery each() function, you are now working with a closure that has the jQuery scope chain, and not your own object's scope chain. Is this on the right track?

thanks

+1  A: 

It doesn't hijack anything - it just makes sure that "this" is pointing at what it wants it to. Look up the standard "call" function that's available for any Javascript function object.

Pointy
+1  A: 

See the documentation for Function.apply. The first parameter is the "context". It can be any object. If null, it will be scoped globally.

Renesis
+13  A: 

You can change the context of a function (i.e. the this value) by calling it with .call() or .apply() and passing your intended context as the first argument.

E.g.

function fn() {
    return this.foo;
}

fn.call({foo:123}); // => 123

Note: passing null to either call or apply makes the context the global object, or, in most cases, window.

It's probably worth noting the difference between .apply() and .call(). The former allows you to pass a bunch of arguments to the function it's being applied to as an array, while the latter lets you just add them as regular arguments after the context argument:

someFunction.apply( thisObject, [1,2,3] );
someFunction.call( thisObject, 1, 2, 3 );

From the jQuery source:

for ( var value = object[0];
      i < length &&
      callback.call( value, i, value ) // <=== LOOK!
      !== false;
      value = object[++i] ) {}
J-P
Note the only difference between call() and apply() is how the function parameters are passed in. One takes them all directly as parameters, the other takes an array of parameters.
Frank Schwieterman
Just added that info. Thanks Frank.
J-P
+1  A: 

The function type in JavaScript has a method called apply() which allows you to specify to what object this is bound at. Its signature is:

apply(thisObj, arguments);

Once called, it calls the function binding this to thisObj and passing the arguments arguments.

It is usually used as such:

function product(name, value)
{
  this.name = name;
  if (value > 1000)
    this.value = 999;
  else
    this.value = value;
}

function prod_dept(name, value, dept)
{
  this.dept = dept;
  product.apply(this, arguments);
}
prod_dept.prototype = new product();

// since 5 is less than 1000 value is set
var cheese = new prod_dept("feta", 5, "food");

// since 5000 is above 1000, value will be 999
var car = new prod_dept("honda", 5000, "auto");
Andrew Moore
+1  A: 

try this:

var MyObject = { "Test": "Hello world!" };
(function ()
{
    alert(this.Test); // Gives "Hello world!"
}).call(MyObject);

(function ()
{
    alert(this.Test); // Gives "Hello world!"
}).apply(MyObject);

(function ()
{
    alert(this.Test); // Gives "undefined"
})()
Andy E
+1  A: 

function.apply() and function.call() allow you to change what this points to in Javascript. Here's a couple of handy articles that explain it in greater detail - Scope In Javascript and Binding Scope in Javascript

Dan F