ECMA-262-3 in detail. Chapter 3. This.

Read this article in: Russian, Chinese (version1, version2).

In this article we will discuss one more detail directly related with execution contexts. The topic of discussion is the this keyword.

As the practice shows, this topic is difficult enough and often causes issues in determination of this value in different execution contexts.

Many programmers are used to thinking that the this keyword in programming languages is closely related to the object-oriented programming, exactly referring the newly created object by the constructor. In ECMAScript this concept is also implemented, however, as we will see, here it is not limited only to definition of created object.

Let’s see in detail what exactly this value is in ECMAScript.

This value is a property of the execution context:

activeExecutionContext = {
  VO: {...},
  this: thisValue
};

where VO is variable object which we discussed in the previous chapter.

This is directly related to the type of executable code of the context. The value is determined on entering the context and is immutable while the code is running in the context.

Let’s consider these cases more in detail.

Here everything is simple enough. In the global code, this value is always the global object itself; thus, it is possible to reference it indirectly:

// explicit property definition of
// the global object
this.a = 10; // global.a = 10
alert(a); // 10

// implicit definition via assigning
// to unqualified identifier
b = 20;
alert(this.b); // 20

// also implicit via variable declaration
// because variable object of the global context
// is the global object itself
var c = 30;
alert(this.c); // 30

Things are more interesting when this is used in function code. This case is the most difficult and causes many issues.

The first (and, probably, the main) feature of this value in this type of code is that here it is not statically bound to a function.

As it has been mentioned above, this value is determined on entering the context, and in case with a function code the value can be absolutely different every time.

However, at runtime of the code this value is immutable, i.e. it is not possible to assign a new value to it since this is not a variable (in contrast, say, with Python programming language and its explicitly defined self object which can repeatedly be changed at runtime):

var foo = {x: 10};

var bar = {
  x: 20,
  test: function () {

    alert(this === bar); // true
    alert(this.x); // 20

    this = foo; // error, can't change this value

    alert(this.x); // if there wasn't an error, then would be 10, not 20

  }

};

// on entering the context this value is
// determined as "bar" object; why so - will
// be discussed below in detail

bar.test(); // true, 20

foo.test = bar.test;

// however here this value will now refer
// to "foo" – even though we're calling the same function

foo.test(); // false, 10

So what affects the variations of this value in function code? There are several factors.

First, in a usual function call, this is provided by the caller which activates the code of the context, i.e. the parent context which calls the function. This value is determined by the form of a call expression.

It is necessary to understand and remember this important point in order to be able to determine this value in any context without any problems. Exactly the form of a call expression, i.e. the way of calling the function, influences this value of a called context and nothing else (as we can see in some articles and even books on JavaScript which claim that “this value depends on how function is defined: if it is global function then this value is set to global object, if function is a method of an object this value is always set to this object” — what is absolutely incorrect). Moving forward, we see that even normal global functions can be activated with different forms of a call expression which influence a different this value:

function foo() {
  alert(this);
}

foo(); // global

alert(foo === foo.prototype.constructor); // true

// but with another form of the call expression
// of the same function, this value is different

foo.prototype.constructor(); // foo.prototype

It is similarly possible to call the function defined as a method of some object, but this value will not be set to this object:

var foo = {
  bar: function () {
    alert(this);
    alert(this === foo);
  }
};

foo.bar(); // foo, true

var exampleFunc = foo.bar;

alert(exampleFunc === foo.bar); // true

// again with another form of the call expression
// of the same function, we have different this value

exampleFunc(); // global, false

So how does the form of the call expression influences this value? In order to fully understand the determination of the this value, it’s necessary to consider in detail one of the internal types — the Reference type.

Using pseudo-code the value of Reference type can be represented as an object with two properties — base (i.e. object to which a property belongs) and a propertyName in this base:

var valueOfReferenceType = {
  base: <base object>,
  propertyName: <property name>
};

Value of Reference type can be only in two cases:

  1. when we deal with an identifier;
  2. or with a property accessor.

Process of identifier resolution is in detail considered in the Chapter 4. Scope chain; and here we just notice that at return from this algorithm always there is a value of Reference type (it is important for this value).

Identifiers are variable names, function names, names of function arguments and names of unqualified properties of the global object. For example, for values on following identifiers:

var foo = 10;
function bar() {}

in intermediate results of operations, corresponding values of Reference type are the following:

var fooReference = {
  base: global,
  propertyName: 'foo'
};

var barReference = {
  base: global,
  propertyName: 'bar'
};

For getting the real value of an object from a value of Reference type there is GetValue method which in a pseudo-code can be described as follows:

function GetValue(value) {

  if (Type(value) != Reference) {
    return value;
  }

  var base = GetBase(value);

  if (base === null) {
    throw new ReferenceError;
  }

  return base.[[Get]](GetPropertyName(value));

}

where the internal [[Get]] method returns the real value of object’s property, including as well analysis of the inherited properties from a prototype chain:

GetValue(fooReference); // 10
GetValue(barReference); // function object "bar"

Property accessors are also know; there are two variations: the dot notation (when the property name is correct identifier and is in advance known), or the bracket notation:

foo.bar();
foo['bar']();

On return of intermediate calculation we also have the value of Reference type:

var fooBarReference = {
  base: foo,
  propertyName: 'bar'
};

GetValue(fooBarReference); // function object "bar"

So, how a value of Reference type is related with this value of a function context? — in the most important sense. The given moment is the main of this article. The general rule of determination of this value in a function context sounds as follows:

This value in a function context is provided by the caller and determined by the current form of a call expression. If on the left hand side from the call parentheses ( ), there is a value of Reference type then this value is set to the base object of this value of Reference type. In all other cases (i.e. with any other value type which is distinct from the Reference type), this value is always null. But since there is no any sense in null for this value, it is implicitly converted to global object.

Let’s show on examples:

function foo() {
  return this;
}

foo(); // global

We see that on the left hand side of call parentheses there is a Reference type value (because foo is an identifier):

var fooReference = {
  base: global,
  propertyName: 'foo'
};

Accordingly, this value is set to base object of this value of Reference type, i.e. to global object.

Similarly with the property accessor:

var foo = {
  bar: function () {
    return this;
  }
};

foo.bar(); // foo

Again we have the value of type Reference which base is foo object and which is used as this value at bar function activation:

var fooBarReference = {
  base: foo,
  propertyName: 'bar'
};

However, activating the same function with another form of a call expression, we have already other this value:

var test = foo.bar;
test(); // global

because test, being the identifier, produces other value of Reference type, which base (the global object) is used as this value:

var testReference = {
  base: global,
  propertyName: 'test'
};

Now we can precisely tell, why the same function activated with different forms of a call expression, has also different this values — the answer is in different intermediate values of type Reference:

function foo() {
  alert(this);
}

foo(); // global, because

var fooReference = {
  base: global,
  propertyName: 'foo'
};

alert(foo === foo.prototype.constructor); // true

// another form of the call expression

foo.prototype.constructor(); // foo.prototype, because

var fooPrototypeConstructorReference = {
  base: foo.prototype,
  propertyName: 'constructor'
};

Another (classical) example of dynamic determination of this value by the form of a call expression:

function foo() {
  alert(this.bar);
}

var x = {bar: 10};
var y = {bar: 20};

x.test = foo;
y.test = foo;

x.test(); // 10
y.test(); // 20

So, as we have noted, in case when on the left hand side of call parentheses there is a value not of Reference type but any another type, this value is automatically set to null and, as consequence, to the global object.

Let’s consider examples of such expressions:

(function () {
  alert(this); // null => global
})();

In this case, we have function object but not object of Reference type (it is not the identifier and not the property accessor), accordingly this value finally is set to global object.

More complex examples:

var foo = {
  bar: function () {
    alert(this);
  }
};

foo.bar(); // Reference, OK => foo
(foo.bar)(); // Reference, OK => foo

(foo.bar = foo.bar)(); // global?
(false || foo.bar)(); // global?
(foo.bar, foo.bar)(); // global?

So, why having a property accessor which intermediate result should be a value of Reference type, in certain calls we get for this value not the base object (i.e. foo) but global?

The matter is that last three calls, after applying of certain operations, have already on the left hand side of call parentheses the value not of Reference type.

With the first case all is clear – there unequivocally Reference type and, as consequence, this value is the base object, i.e. foo.

In the second case there is a grouping operator which does not apply, considered above, method of getting the real value of an object from value of Reference type, i.e. GetValue (see note of 11.1.6). Accordingly, at return from evaluation of the grouping operator – we still have a value of Reference type and that is why this value is again set to the base object, i.e. foo.

In the third case, assignment operator, unlike the grouping operator, calls GetValue method (see step 3 of 11.13.1). As a result at return there is already function object (but not a value of Reference type) which means that this value set to null and, as consequence, to global.

Similarly with the fourth and fifth cases – the comma operator and logical OR expression call the GetValue method and accordingly we lose value of type Reference and get value of type function; and again this value is set to global.

There is a case when call expression determinates on the left hand side of call parentheses the value of Reference type, however this value is set to null and, as consequence, to global. It is related to the case when the base object of Reference type value is the activation object.

We can see this situation on an example with the inner function called from the parent. As we know from the second chapter, local variables, inner functions and formal parameters are stored in the activation object of the given function:

function foo() {
  function bar() {
    alert(this); // global
  }
  bar(); // the same as AO.bar()
}

The activation object always returns as this value — null (i.e. pseudo-code AO.bar() is equivalent to null.bar()). Here again we come back to the described above case, and again, this value is set to global object.

The exception can be with a function call inside the block of the with statement in case if with object contains a function name property. The with statement adds its object in front of scope chain i.e. before the activation object. Accordingly, having values of type Reference (by the identifier or a property accessor) we have base object not as an activation object but object of a with statement. By the way, it relates not only to inner, but also to global functions because the with object shadows higher object (global or an activation object) of the scope chain:

var x = 10;

with ({

  foo: function () {
    alert(this.x);
  },
  x: 20

}) {

  foo(); // 20

}

// because

var  fooReference = {
  base: __withObject,
  propertyName: 'foo'
};

The similar situation should be with calling of the function which is the actual parameter of the catch clause: in this case the catch object is also added in front of scope chain i.e. before the activation or global object. However, the given behavior was recognized as a bug of ECMA-262-3 and is fixed in the new version of standard — ECMA-262-5; thus, this value in the given activation should be set to global object, but not to catch object:

try {
  throw function () {
    alert(this);
  };
} catch (e) {
  e(); // __catchObject - in ES3, global - fixed in ES5
}

// on idea

var eReference = {
  base: __catchObject,
  propertyName: 'e'
};

// but, as this is a bug
// then this value is forced to global
// null => global

var eReference = {
  base: global,
  propertyName: 'e'
};

The same situation with a recursive call of the named function expression (more detailed about functions see in Chapter 5. Functions). At the first call of function, base object is the parent activation object (or the global object), at the recursive call — base object should be special object storing the optional name of a function expression. However, in this case this value is also always set to global:

(function foo(bar) {

  alert(this);

  !bar && foo(1); // "should" be special object, but always (correct) global

})(); // global

There is one more case related with this value in a function context – it is a call of function as the constructor:

function A() {
  alert(this); // newly created object, below - "a" object
  this.x = 10;
}

var a = new A();
alert(a.x); // 10

In this case, the new operator calls the internal [[Construct]] method of the “A” function which, in turn, after object creation, calls the internal [[Call]] method, all the same function “A”, having provided as this value newly created object.

There are two methods defined in the Function.prototype (therefore they are accessible to all functions), allowing to specify this value of a function call manually. These are .apply and .call methods; both of them accept as the first argument this value which is used in a called context. A difference between these methods is insignificant: for the .apply the second argument necessarily should be an array (or, the array-like object, for example, arguments), in turn, the .call method can accept any arguments; obligatory arguments for both methods is only the first — this value.

Examples:

var b = 10;

function a(c) {
  alert(this.b);
  alert(c);
}

a(20); // this === global, this.b == 10, c == 20

a.call({b: 20}, 30); // this === {b: 20}, this.b == 20, c == 30
a.apply({b: 30}, [40]) // this === {b: 30}, this.b == 30, c == 40

In this article we have discussed features of the this keyword in ECMAScript (and they really are features, in contrast, say, with C++ or Java). I hope article helped to understand more accurately how this keyword works in ECMAScript. As always, I am glad to answer your questions in comments.

10.1.7 – This;
11.1.1 – The this keyword;
11.2.2 – The new operator;
11.2.3 – Function calls.


Translated by: Dmitry A. Soshnikov with help of Stoyan Stefanov.
Published on: 2010-03-07

Originally written by: Dmitry A. Soshnikov [ru, read »]
With additions and corrections by: Zeroglif

Originally published on: 2009-06-28; updated on: 2010-03-07


Tags: , ,

 
 
 

21 Comments:

  1. Gravatar of denisdeng denisdeng
    19. April 2010 at 16:31

    Thank you,I have finisehd this article.
    ECMA-262-3 深入解析.第三章.this


  2. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    19. April 2010 at 16:35

    @denisdeng

    OK, well done, Denis. I added a link to your translation.


  3. Gravatar of denisdeng denisdeng
    19. April 2010 at 16:36

    Thank you!


  4. Gravatar of Yonatan Yonatan
    23. April 2010 at 18:16

    Thanks a lot for this wonderful series of articles!


  5. Gravatar of justin justin
    28. April 2010 at 20:06

    hi , one question:
    But since there is no any sense in null for this value, it is implicitly converted to global object.

    Can I understand like this:

    The actual value of “this” does not exist null situation.
    When this value is null ,then the value will be implicitly converted to the global object.


  6. Gravatar of justin justin
    28. April 2010 at 20:12

    another question:
    …the form of a call expression …

    I think the “expression” means “FunctionExpression” in the previous chapter

    right?


  7. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    28. April 2010 at 23:21

    @Yonatan

    thanks.

    @justin

    Can I understand like this:

    The actual value of “this” does not exist null situation.
    When this value is null ,then the value will be implicitly converted to the global object.

    Yup, that’s right.

    …the form of a call expression …

    I think the “expression” means “FunctionExpression” in the previous chapter

    right?

    Nope, a FunctionExpression is an expression which defines special type of function.

    And by “form of a call expression” I mean the view by which function context is activated:

    function F() {}
    
    // one view - "F" of call expression
    F();
    
    // another view - "F.prototype.constructor"
    // of call expression for the same function
    F.prototype.constructor();

    So, it is how (in which view) function is activated. That exactly the one of the main factors influence this value.

    Dmitry.


  8. Gravatar of justin justin
    29. April 2010 at 04:48

    thanks!
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Nope, a FunctionExpression is an expression which defines special type of function.

    And by “form of a call expression” I mean the view by which function context is activated:
    function F() {}

    // one view – “F” of call expression
    F();

    // another view – “F.prototype.constructor”
    // of call expression for the same function
    F.prototype.constructor();

    So, it is how (in which view) function is activated. That exactly the one of the main factors influence this value.
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    so,I translaste “form of a call expression”to chinese is “Way of calling the function”(调用函数的方式).
    “form of a call expression” is too abstract, difficult to understand.

    What do you think?

    btw:”exactly referring the the newly created object by the constructor. ” , I think maybe you want to only one “the”.


  9. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    29. April 2010 at 10:35

    @justin

    so,I translaste “form of a call expression”to chinese is “Way of calling the function”(调用函数的方式).

    “form of a call expression” is too abstract, difficult to understand.

    What do you think?

    Yep, I think the “way of calling the function” is a good clarification. I added this phrase also.

    btw:”exactly referring the the newly created object by the constructor. ” , I think maybe you want to only one “the”.

    Yep, it was a typo, thanks; fixed.

    Dmitry.


  10. Gravatar of justin justin
    29. April 2010 at 18:02

    thanks!

    I’m not very smart, I still have some other questions:
    1.In the third case, assignment operator, unlike the grouping operator, calls GetValue method.
    “calls GetValue method” ,why and where I can kown ” assignment operator will >calls GetValue method.”

    2.The activation object always returns as this value — null (i.e. pseudo-code AO.bar() is equivalent to null.bar()).

    AO is always null?why?


  11. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    29. April 2010 at 19:13

    @justin

    1.In the third case, assignment operator, unlike the grouping operator, calls GetValue method.
    “calls GetValue method” ,why and where I can kown ” assignment operator will >calls GetValue method.”

    See 11.13.1 Simple Assignment ( = ), step 3. I added it to the article also.

    2.The activation object always returns as this value — null (i.e. pseudo-code AO.bar() is equivalent to null.bar()).

    AO is always null?why?

    See 10.1.6 Activation Object. The last sentence:

    When the call operation is applied to a Reference value whose base object is an activation object, null is used as the this value of the call.”

    If you read attentively Chapter 2. Variable object, you should know that inner function declarations are stored in the activation object (AO) of the parent function:

    function foo() {
      function bar() {}
      bar();
    }
    
    // activation object
    // of foo context
    AO(foo) = {
      bar: function bar() {}
    };

    So when bar function is called inside the foo function, the intermediate Reference type value is:

    var barReference = {
      base: AO(foo),
      propertyName: "bar"
    };

    And then we see definition from the spec, that in such case should be used null instead of AO(bar).

    Dmitry.


  12. Gravatar of justin justin
    29. April 2010 at 19:57

    thanks a lot ~
    about 2, I know “inner function declarations are stored in the activation object (AO) of the parent function”,but I don’t know “10.1.6 Activation Object. The last sentence:“; so,It’s too difficult to me to understand that.

    about 1,if I read “11.13.1 Simple Assignment ( = ), step 3″ in advance,It’s easy enough to understand.

    there is another question:
    if it is nessary for me to read ECMA-262-3 firstly,and then to read this set of articles? or could you do our a favour and add comments in details to the content which are from ECMA-262-3 in your articles.
    your help would be great appreciated!


  13. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    29. April 2010 at 21:19

    @justin

    but I don’t know “10.1.6 Activation Object. The last sentence:“; so,It’s too difficult to me to understand that.

    I didn’t understand completely this sentence. Is it clear now, or it still difficult to understand? If still, ask again, I’ll explain more detailed.

    there is another question:
    if it is nessary for me to read ECMA-262-3 firstly,and then to read this set of articles?

    No, of course not. This series is exactly detailed explanation of the ECMA-262-3 specification. If you have already read the spec — it is good. But if not yet — it isn’t required strictly because many explanations are in these articles, and presented in more “human-view” (i.e. should be easier to understand than standard), but not just dry theoretical algorithms descriptions from the spec.

    You of course can read specification simultaneously with reading this series.

    or could you do our a favour and add comments in details to the content which are from ECMA-262-3 in your articles

    Actually, many parts in this series are from the ECMA-262-3, and, repeat, this series — is exactly detailed explanation of the ECMA-262-3. So some related sections of the specification I always mention in the last section of every article — in the section of additional literature. But, yeah, I’ll try to put more references to the specification directly within content. Moreover, all vaguenesses can be clarified in comments and then, if needed, I’ll add references to the spec directly in-place.

    Dmitry.


  14. Gravatar of justin justin
    30. April 2010 at 05:02

    hi,Dmitry
    thanks for your reply!

    It’s clear now,I think my express of “about 2″ make your misleading,my mean is that I don’t know what“10.1.6 Activation Object. The last sentence:“ is before,because I didn’t konw it from ECMA-262-3, but I could understand it after your explaination.

    however,I think “more references to the specification directly within content” is great help for us who didn’t read ECMA-262-3.


  15. Gravatar of justin justin
    4. May 2010 at 14:22

    I finally finished this chapter translation:http://www.cnblogs.com/justinw/archive/2010/05/04/1727295.html

    btw:
    “The same situation with a recursive call of the named function expression”
    named function expression links to the wrong address


  16. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    4. May 2010 at 19:27

    @justin

    I finally finished this chapter translation

    Well done; added your translation.

    named function expression links to the wrong address

    Yep, thanks; fixed.

    Dmitry.


  17. Gravatar of leoner leoner
    7. May 2010 at 12:38

    var x = 20;
    function fn(){
        function f1(){
            console.log(this.x)
        }
        with({
            f2: function(){
                console.log(this.x)
            },
            x:50
        }){
            function f3(){
                console.log(this.x)
            }
             function f4(){
                console.log(x)
            }
            f1();//20
            f2();//50
            f3();//20
            f4();//50
        }
    }
    fn()

    can you help me explain f1,f3,f4 why value is 50,20,50?
    I am a little confused.


  18. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    7. May 2010 at 18:58

    @leoner

    can you help me explain f1,f3,f4 why value is 50,20,50?

    In order to be able to answer this question precisely, you have to learn first the topic about variable object and stages of its modifications, i.e. — entering the context and the code execution stage.

    Therefore, on entering the fn’s function context, created three function declarations: f1, f3 and f4. This code can be transformed to:

    function fn(){
        function f1(){
            console.log(this.x)
        }
        function f3(){
            console.log(this.x)
        }
        function f4(){
            console.log(x)
        }
        with (...) {
            ...
        }
    }
    

    Function f1 and f3 then are equivalent. Both use this value as a prefix for x property.

    Then you know from corresponding section of the current article, that if the base component of a Reference type value is an activation object, then should be used null => global as this value.

    All three (f1, f3, f4) are stored in the activation object of the fn function and corresponding reference value for all them is:

    var f1Reference = {
      base: AO(fn), // => global
      propertyName: "f1"
    };

    The same for f3 and f4. That means that this value at f1, f3 and f4 activations — is the global object. And accordingly this.x leads to 20 — i.e. the x variable value defined in the global context.

    So the correct answer for f1 and f3 is 20.

    In contrast, f4 doesn’t use this.x, but just x. Where this name binding x should be resolved? It depends on scope chain lookup (for detailed explanation see Chapter 4. Scope chain).

    If f4 will be executed outside the with statement, then x name binding is resolved in the global object and is 20. You can check executing it before or after with statement.

    But in your example f4 executes inside the with statement. And you should know (from the 4th chapter) that with adds its object in the front of scope chain. I.e. scope chain of the fn function context is now looks like:

    Scope = [global, AO(fn), {f2: funciton () {...}, x: 50}]

    So calling f4 inside with, x variable will be resolved to 50, because will be found earlier than global’s 20. And that’s correct answer for your f4 is 50.

    Note however, if you create a function expression then x will be resolved always to 50 even outside the with:

    var foo;
    
    with ({x: 50}) {
      foo = function () {
        console.log(x);
      };
      foo(); 50;
    }
    
    var x = 20;
    foo(); // 50, but not 20

    Because functions in JS are closures and use lexical (static) scoping, i.e. saves parent scope chain at creation of the function.

    And f2 funciton being a function expression in contrast with function declarations is created at code execution stage and is a property of with’s statement object.

    Therefore, a reference type value for f2 is:

    var f2Reference = {
      base: withObject,
      propertyName: "f2"
    };

    And accordingly, withObject is used as this value at f2 activation. And you set x as 50 for with’s object. Therefore, the correct answer for f2 is 50.

    Dmitry.


  19. Gravatar of leoner leoner
    10. May 2010 at 06:13

    Thank you for you replay,I understand.:)


  20. Gravatar of tiger tiger
    6. June 2010 at 10:13

    hi,Dmitry

    when i read the ecma 10.4.3 Entering Function Code ,it says “The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList: ”
    i don’t understand the caller and the thisArg.

    could you explain what they mean

    thanks


  21. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    6. June 2010 at 17:45

    @tiger

    i don’t understand the caller and the thisArg.

    could you explain what they mean

    A caller — is a context which invokes (calls) some other context.

    If we have foo function and call it from the global context, then the global context is the caller of the foo.

    You can test a caller value via the non-standard (and deprecated) property with the same name of a function object, e.g. foo.caller, or a property of the arguments inside a function — arguments.caller. In SpiderMonkey for the global context a caller is null for other — a function from which a particular function is being called:

    function foo() {
      alert(foo.caller);
    }
    
    // call
    foo(); // a caller is the global (null here)

    Accordingly, if we call the same function from some other context, a caller will be other:

    function bar(callback) {
      callback(); // a caller is "bar" function context
    }
    
    bar(foo);

    In turn, a context which is being called is a callee. That’s why arguments.callee at execution of a function refers to itself — because it’s currently being called by a caller and is a callee.

    Notice, if you’ll test this code in Firebug console, in the first example a caller is a context of the evaluation console’s code, but not the global.

    So if some context (a caller) calls another context (a callee), then exactly a caller provides a this value and argument values for a function context.

    This value is provided via the form of a call expression, i.e. the way of how (the same) function is executed:

    var x = 10;
    
    function foo(y) {
      alert([this.x, y]);
    }
    
    foo.prototype.x = 50;
    
    function bar(callback) {
    
      // here for "callback" the caller is "bar"
      // and the callee is "callback",
      // and the caller provide this value (thisArg)
      // and arguments (argumentsList) for the callee
    
      // "bar" provides "this" as AO => global,
      // arguments as [20]
      callback(20); // 10, 20
    
      // "bar" provides "this" as {x: 30},
      // arguments as [40, 50]
      callback.call({x: 30}, 40, 50); // 30, 40
    
      // "bar" provides "this" as {x: 100},
      // arguments as [1, 2, 3]
      callback.apply({x: 100}, [1, 2, 3]);  // 100, 1
    
      // "bar" provides "this" as "callback.prototype"
      // arguments as [60]
      callback.prototype.constructor(60); // 50, 60
    
    }
    
    bar(foo);

    Dmitry.


Leave a Reply

Code: For code you can use tags [js], [text], [ruby] and other.

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>