Hi Rob, thanks for the comments.

Aren't we saying the same thing, though?

> > From: Michael Geary
> > To elaborate a bit, "this" is special, but it's not magic.
> >
> > Whenever you call a function in JavaScript, it's always called as a 
> > method of some object,

> From: RobG
> No, it's not.  What object is the following functions called 
> as methods of:
> 
> (function(){})();

That anonymous function is called as a method of the global (window) object,
and 'this' is the global object when the function is executing.

When I say "called as a method of", what I mean specifically is "called with
'this' as a reference to". After all, 'this' is how a function knows what
it's being called as a method of - 'this' is how the function accesses that
object.

We could say something like "called *as if it were* a method of", but that
would really be saying the same thing. A function doesn't have any object
that it is "really" a method of, that's determined by the caller.

> function foo() {};
> foo.call({});

foo is called as a method of the {} object. To expand the example a bit:

function foo() { alert this.a; }
foo.call({ a:'b' });  // alerts "b"

> > and this is a reference to that object.
> 
> If an object can't be determined, the global object is used, hence:
> 
>   var global = (function(){return this;})();

Right, we're saying the same thing. When a function is called, it's always
called as a method of *some* object, the only question is which object. It's
up to the caller to specify that object through object.method() or
object['method']() notation, or through .apply() or .call(), and if no
object is specified, the global object is used.

> > When you call foo.bar(), you are calling a function as a 
> > method of the foo object, so this == foo.
> >
> > JavaScript also has a global object. When you call a
> > function bar() without any explicit object reference, you
> > are actually calling it as a method of the global object.

> No, they aren't.  Properties resolved on the scope chain 
> don't behave like that, otherwise this used within methods 
> found on prototype objects would refer to the prototype 
> object rather than the instance.

I'm a little confused here. Are you talking about the scope chain or the
prototype chain?

In any case, how and where the function is located doesn't affect 'this'.
It's how the function is *called* that determines the 'this' object.

Here's an example with the same function in two different prototypes:

function One() {}
One.prototype.prop = 'ONE';

function Two() {}
Two.prototype.prop = 'TWO';

One.prototype.test = Two.prototype.test = function( label ) {
    console.log( label, this.constructor, this.prop );
};

var one = new One;
var two = new Two;

one.test( "one.test():" );
one['test']( "one['test']()" );

two.test( "two.test:()" );
two['test']( "two['test']():" );

one.test.call( two, "one.test.call(two):" );
two.test.call( one, 'two.test.call(one):' );

var oneTest = one.test;
var twoTest = two.test;

oneTest( "oneTest():" );
twoTest( "twoTest():" );

oneTest.call( two, "oneTest.call(two):" );
twoTest.call( one, 'twoTest.call(one):' );

That code logs the following:

one.test(): One() ONE
one['test']() One() ONE
two.test:() Two() TWO
two['test'](): Two() TWO
one.test.call(two): Two() TWO
two.test.call(one): One() ONE
oneTest(): Window undefined
twoTest(): Window undefined
oneTest.call(two): Two() TWO
twoTest.call(one): One() ONE

As this shows, it's the caller that determines the 'this' object in each
case.

> The global object is used when no other reference can be 
> resolved or the call sets it to the this keyword.

That's right, as shown in the oneTest/twoTest examples, the function is
called as a method of the global object (called with 'this' set to the
global object) in those cases.

-Mike

Reply via email to