in ECMAScript

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

Read this article in: Russian.

Introduction

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.

Definitions

this is a property of the execution context. It’s a special object in which context a code is executed.

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.

This value in the global code

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
console.log(a); // 10

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

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

This value in the function code

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 () {

    console.log(this === bar); // true
    console.log(this.x); // 20
    
    this = foo; // error, can't change this value
 
    console.log(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. And the value of this is determined by the form of a call expression (in other words by the form how syntactically the function is called).

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 mistaken description). 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() {
  console.log(this);
}

foo(); // global

console.log(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 () {
    console.log(this);
    console.log(this === foo);
  }
};

foo.bar(); // foo, true

var exampleFunc = foo.bar;

console.log(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.

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>
};
Note: since ES5 a reference also contains property named strict — the flag whether a reference is resolved in the strict mode.

'use strict';

// Access foo.
foo;

// Reference for `foo`.
const fooReference = {
  base: global,
  propertyName: 'foo',
  strict: true,
};

Value of Reference type can be only in two cases:

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

Identifiers are handled by the process of identifiers resolution which 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:

The value of this in a function context is provided by the caller and determined by the current form of a call expression (how the function call is written syntactically).

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 set to 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'
};

Note, in the strict mode of ES5 this value is not coerced to global object, but instead is set to undefined.

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() {
  console.log(this);
}

foo(); // global, because

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

console.log(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() {
  console.log(this.bar);
}

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

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

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

Function call and non-Reference type

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 () {
  console.log(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 () {
    console.log(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.

Reference type and null this value

There is a case when call expression determines 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() {
    console.log(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 () {
    console.log(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. I.e. this value in the given activation should be set to global object, but not to catch object:

try {
  throw function () {
    console.log(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) {

  console.log(this);

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

})(); // global

This value in function called as the constructor

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

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

var a = new A();
console.log(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.

Manual setting of this value for a function call

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) {
  console.log(this.b);
  console.log(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

Conclusion

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.

Additional literature

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

Write a Comment

Comment

111 Comments

  1. Thanks a lot for this wonderful series of articles!

  2. 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.

  3. another question:
    …the form of a call expression …

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

    right?

  4. @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.

  5. 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”.

  6. @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.

  7. 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?

  8. @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.

  9. 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!

  10. @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.

  11. 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.

  12. @justin

    I finally finished this chapter translation

    Well done; added your translation.

    named function expression links to the wrong address

    Yep, thanks; fixed.

    Dmitry.

  13. 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.

  14. @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 (update: not executed, but defined; see explanation below. It’s only in Firefox, f4 is a function statement!) 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 (update: also, f4 has nothing with scope chain of fn!). 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.

  15. Thank you for you replay,I understand.:)

  16. 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

  17. @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.

  18. Wow, amazing article, thanks.

    Its turns out that now I am JS Rebel, I dont believe anymore
    in any book(lol), just on specifications!!

  19. var input = document.createElement('input');
    input.type="button";
    input.value="test2";
    
    var aa = function(){
        alert(this.value);
        if(!-[1,])
           input.detachEvent('onclick',aa);
        else
           input.removeEventListener('click',aa);
    };
    if(!-[1,])
        input.attachEvent('onclick',aa);
    else
        input.addEventListener('click',aa);
    
    document.body.appendChild(input);
    

    can you help me explain why this equal input?
    think you!

  20. @huoyue2010

    can you help me explain why this equal input?

    Because when aa function is activated by the click event, the this value is bound to the input element. Always remember, that this value is bound dynamically exactly at activation moment.

    It’s the same as it would be (in a very simplified manner):

    var input = {
      handlers: {
        click: [],
        // other events
      },
      addEventListener: function (event, fn) {
        this.handlers[event].push(fn);
      },
      // generic handler of events
      activate: function (event) {
        this.handlers[event].forEach(function (fn) {
          var eventData = {...};
          fn.call(this, eventData);
        }, this);
      }
    };

    Dmitry.

  21. Superb articles!
    one qs about the explanation for the comment from ‘leoner’ (above),
    when I ran it chrome, it gave

    f1();//20
    f2();//50
    f3();//20
    f4();//20 NOT 50

    I don’t really get hold this.
    Why did it print 20 ?

    function f4(){
       console.log(x)
    }
  22. @sojin, what a my mistake in that reply to leoner! Thanks for figuring it out. I’ve edited the previous reply with striking the wrong part of explanation.

    It’s not completely wrong of course; it’s correct for exactly Firefox (in which console seems I was testing the code).

    As you probably know Firefox defines a special type of functions which are called Function Statements. This extension allows to define functions conditionally in e.g. if-blocks. In all other current implementations a function declaration is independent from the conditional if-block.

    if (true) {
      function foo() {
        alert(1);
      }
    } else {
      function foo() {
        alert(2);
      }
    }
    
    foo(); // 1 in FF, 2 - in other
    

    So in case of that example f4 as shown in the reply to leoner is hoisted to the top and saves the parent scope chain at the moment of its definition. At this moment of course there is no that {x: 5} added by the with.

    And in Chrome (and other) the behavior is correct. It should be 20 in the last call. But, in Firefox the behavior is also correct — depending on its Function Statement extension (which behaves similarly in this respect to Function Expressions as shown in that reply). And in FF it should be 50 in the last call.

    The future version of ECMAScript should standardize function statements, and then the correct result should be as in FF, i.e. 50. But now, both are correct. Since function declarations in blocks (which are function statements) are not defined by the current spec and are extensions with their own behavior. Though, the behavior of FF seems more logical to me.

    Dmitry.

  23. Hello Dmitry,
    First of all, thank you for so interesting series of articles. It is absolutely unique and definitely deserves to be published.

    I am reading this chapter and specifically work on this pieces of code:

    var foo = 10;
    function bar() {}
     
    var fooReference = {
      base: global,
      propertyName: 'foo'
    };
     
    var barReference = {
      base: global,
      propertyName: 'bar'
    };
    
     
    function GetValue(value) {
     
      if (Type(value) != Reference) {
        return value;
      }
     
      var base = GetBase(value);
     
      if (base === null) {
        throw new ReferenceError;
      }
     
      return base.[[Get]](GetPropertyName(value));
     
    }
    
     
    GetValue(fooReference); // 10
    GetValue(barReference); // function object "bar"

    I realize that the code above is partially a pseudo-code, but I am still trying to
    to modify it and run to see in action what is actually going on here.

    I am not sure how to interpret the “base:global” expression in both fooReference and barReference variables. GetValue() function is also kind of vaguely defined.

    Can you please provide the same (or similar) code fragment in the form that can be actually executed (let’s say in Firebug debugger) and would be useful in exploring this internal machinery? This is a key point to understanding “this” so more details about the Reference type would be extremely useful.
    Thanks in advance!

  24. @Luiz

    Yes, as you correctly noted, it’s a pseudo-code and just corresponds to the technical algorithm of the specification.

    I am not sure how to interpret the “base:global” expression

    Well, for the global we may use direct this value in the global context as is mentioned in the appropriate section above. I.e.:

    var global = this;

    Alternatively, in the browser environment, we can use window binding to refer the global object (though, this is more correct).

    var global = window;

    GetValue() function is also kind of vaguely defined.

    Can you please provide the same (or similar) code fragment in the form that can be actually executed (let’s say in Firebug debugger) and would be useful in exploring this internal machinery?

    Yeah, first, GetValue described here is a pseudo-code reflection of the corresponding algorithm of the ES5/ES5 spec. Take a look on it — here (I used ES3 version when was writing this chapter, ES5 version is slightly modified, but the main part is the same).

    A value of Reference type as mentioned is a pair: base and propertyName. It can be presented as a constructor in plain JS:

    function Reference(base, propertyName) {
      this.base = base;
      this.propertyName = propertyName;
    }

    When interpreter meets a variable/function name (or in other words — an identifier), it resolves it — i.e. it searches it in the scope chain. This is a process of the identifier resolution which is described in the Chapter 4 Scope chain.

    The thing interesting to us, is that the result of the identifier resolution mechanism is always the value of type reference.

    If the identifier is found in the scope chain — return the value of Reference type with base containing that variable object in which the identifier is found (scope chain as you probably know or will learn in the next chapter 4 is a chain of variable objects from different nested contexts).

    If the identifier is not found — also the value of Reference type is returned, but with base component equals to null.

    And then, if to transform our pseudo-code of GetValue more closely to JS, we’ll get:

    function getValue(v) {
      if (v instanceof Reference) {
        if (!v.base) {
          throw new ReferenceError(v.propertyName +
             " is not defined");
        }
        return v.base[v.propertyName];
      }
      return v;
    }

    And if we have, e.g. global variable x:

    var x = 10;

    then after the identifier resolution mechanism, we get the following value of the Reference type:

    var xReference = new Reference(global, "x");

    Notice, it’s an intermediate result of some calculation, it’s not the real value of x yet, i.e. 10. To get exactly the value of x, already getValue is applied:

    getValue(xReference); // 10

    If in contrast we refer a non-existing variable from the code, e.g. y, then as we said, we also get the value of Reference type, but with base set to null:

    var yReference = new Reference(null, "y");

    Such intermediate results (of the Reference type) are very important to JS. E.g. exactly via it the work of typeof operator is explained. We won’t get an error in the following code:

    alert(typeof y); // "undefined"

    because typeof doesn’t call getValue, it just works with the reference itself. However, we do get the ReferenceError if try to just alert the y:

    alert(y); // "ReferenceError": y is not defined

    and now we know why — because we provided such a behavior in the getValue. Function alert to display the value of the variable, should call getValue:

    getValue(yReference); // y is not defined

    And in the similar respect determination of this value for function calls works. If on the left-hand side (LHS) is the value of Reference type, then this is set to the base of reference

    var foo = {
      bar: function () {
        alert(this);
      }
    };
     
    foo.bar(); // Reference, OK => foo

    Grouping operator, the same as typeof also doesn’t call our getValue, which means either with, or without grouping operator — we still have the reference value:

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

    However, assignment (the same as alert above with y) does call getValue and after its work we already have not the value of Reference type, but the function value, and as a result — this value is set to null and then converted (in ES3) to global object:

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

    That is — a shorter, but detailed description of these algorithms. Feel free to ask questions if is needed to clarify something.

    Dmitry.

  25. Dmitry,
    thanks a lot for a detailed explanation. It’s a lot of food for thought.
    Meanwhile this code fragment below runs OK with two exceptions:

    1) In function getValue() I had to use return v.base instead of v.base[v.propertyName];
    2) for undefined var y ReferenceError is not called in the statements like:

    alert(y);

    or

    document.write("Value of 'y': ", getValue(yReference));
    //========================================================//
    
    var x = 10;
    
    var xReference = new Reference(x,"x");
    document.write("Type of 'x': ", typeof x ); 
    document.write("Value of 'x': ", getValue(xReference));
    
    var yReference = new Reference(null,"y"); 
    document.write(getValue(yReference));  // works, "Reference Error"
    document.write("Type of 'y': ", typeof y );    			//does not work
    document.write("Value of 'y': ", getValue(yReference)); //does not work
     
     
     
    function Reference(base, propertyName) {
      this.base = base;
      this.propertyName = propertyName;
    }
    
    function ReferenceError(error) {
     document.write("Reference Error: ", error);
    } 
    
    function getValue(v) {
      if (v instanceof Reference) {
        if (!v.base) {
          throw new ReferenceError(v.propertyName + " is not defined");
        }
        return v.base;  //instead of v.base[v.propertyName];
      }
      return v;
    }
    
    //==================================================//

    Thank you.
    Luiz.

  26. @Luiz

    1) In function getValue() I had to use return v.base instead of v.base[v.propertyName];

    No, it’s not correct, should be nevertheless v.base[v.propertyName].

    The mistake you made is that you used not correct base component for e.g. x reference. You used x as the base, but it should be the global object. Once again, the base component of the reference is an object to which the property belongs. Global variable x belongs to global object, therefore global object is its base.

    You have (wrong):

    var x = 10;
    
    // wrong 
    var xReference = new Reference(x,"x");

    and it should be:

    // global object -- we need it to
    // use as a base of global variables!
    
    var global = this;
    
    var x = 10;
     
    // base is "global" (not "x" as in your example),
    // since variable "x" is a global variable
    
    var xReference = new Reference(global, "x");

    Also if you defined your own ReferenceError constructor (though, it’s a native built-in function), then for tests you may not throw it in getValue, but just return. So the complete code to test may look like this:

    // global object
    var global = this;
    
    // global variable "x"
    var x = 10;
    
    // reference for global variable "x":
    // base: global, propertyName: "x"
    var xReference = new Reference(global, "x");
    
    console.log("Type of 'x': ", typeof x); // "number"
    console.log("Value of 'x': ", getValue(xReference)); // 10
    
    // unresolved reference for non-existing
    // variable "y" (i.e. base is null)
    
    var yReference = new Reference(null, "y");
    
    console.log("Type of 'y': ", typeof y ); // "undefined"
    console.log("Value of 'y': ", getValue(yReference)); // ReferenceError
    
    function Reference(base, propertyName) {
      this.base = base;
      this.propertyName = propertyName;
    }
    
    function ReferenceError(error) {
        return "Reference Error: " + error;
    }
    
    function getValue(v) {
      if (v instanceof Reference) {
        if (!v.base) {
          return ReferenceError(v.propertyName + " is not defined");
        }
        return v.base[v.propertyName];
      }
      return v;
    }

    Dmitry.

  27. Dmitry,
    thanks a lot for taking time to explain the details. Those are pretty subtle issues that are not discussed anywhere except your articles.

  28. Dmitry,I have test the code in the firefox and chrome.but some thing is not appear as you said.

     var foo={
                bar:function(){
                    return this;
                }
            };
            console.log(foo.bar());//foo
            //Again we have the value of type Reference which base is foo object and which
            //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;
            console.log(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'
                //}
                
            function fooTwo(){
                return this;
            }
            console.log("fooTwo===fooTwo.prototype.constructor:",fooTwo===fooTwo.prototype.constructor);
    console.log(fooTwo());
    console.log(fooTwo.prototype.constructor()); 

    the resluts is :

    Object { bar=function()}
    Window 
    fooTwo===fooTwo.prototype.constructor: true
    Window 
    fooTwo {}

    could you give me some suggests about this question.thank u

  29. @Shawn

    I see correct output in your example. I guess output format of the consoles may confuse, but:

    foo.bar(); correctly matches to Object { bar=function()} — this is the foo object.

    test() maps to the Window which is the global object in the browser environment.

    fooTwo===fooTwo.prototype.constructor: true is really true.

    fooTwo() also correctly shows Window (global).

    fooTwo {} maps to fooTwo.prototype.

  30. Hi, Dmitry,

    Could you explain please why in IE9 the code in this comment gives f4();//20, but in Firefox f4();//50? What is the reason of such behavior?

    Thanks

  31. I Dmitry, i am big fan of yours.
    Question: Why there is difference between x and y final output??

    Example Code is:

    Object.prototype.x = 10;
    
    var x = 20;
    var y = 40;
    var z = 60;
    var kk = x + 40;
    
    with ({w:100}) {
      var w = 200;
      Object.prototype.x = 30;
      var x = 50;
      var y = 70;
      var a = 80;
      console.log('here');
    }
    
    console.log(x); // why x is not changed.
    console.log(y); // why y is changed.
    
  32. @Navneet Goel

    This is because of two-dimentional scope-chain look-up. The x binding is found in Object.prototype instead of the global context (since along with the with object — the {w: 100}, its prototype is considered at searching the variable — and this prototype is the Object.prototype).

    However, since assignment should occur on the own object, then the with object is updated instead of modifying the property x on the Object.prototype.

    Object.prototype.x = 10;
    var x = 20;
    var o = {w: 100};
    
    with (o) {
      x = 50;
    }
    
    console.log(
      x, // still 20
      o, // {w: 100, x: 50}
      Object.prototype.x // still 10
    );
    

    In contrast with:

    var x = 20;
    var o = {w: 100};
    
    with (o) {
      x = 50;
    }
    
    console.log(
      x, // 50
      o // {w: 100}
    );
    

    More in detail two-dimentional scope-chain look-up (with the picture) is described — here.

  33. thanks for sharing

        var x = 10;
    
        function foo(){
            var x = 20;
            function bar(){ // case a
                var x = 30;
                alert(x);// 30 - case b
        // from Chapter 3 This
        // 27. February 2011 at 18:38 @Luiz
        // "When interpreter meets a variable/function name (or in other words — an identifier), it resolves it —
        // i .e. it searches it in the scope chain. This is a process of the identifier resolution which is described in the Chapter 4 Scope chain."
        //  ... from chapter 4 Scope chain
        // "Identifier resolution is a process of determination to which variable object in scope chain the variable (or the function declaration) belongs."
        // "On return from this algorithm we have always a value of type Reference, which base component is the corresponding variable object (or null if variable is not found),
        // and a property name component is the name of the looked up (resolved) identifier."
    
        /* case a) I assume calling bar:
         * fooContext.scope = [fooContext.AO, globalContext.VO]
         * var barReference =
         * {
         *   base: fooContext.AO,
         *   propertyName: 'bar'
         * }
         */
    
        /* case b) I assume resolving x:
         * barContext.scope = [barContext.AO, fooContext.AO, globalContext.VO]
         * var xReference =
         * {
         *   base: barContext.AO,
         *   propertyName: 'x'
         * }
         * calling GetValue we have the real value of x
         */
    
         alert(this); // case c
        // from Chapter 3 This
        // "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."
    
        /* case c) I assume:
         * fooContext.scope = [fooContext.AO, globalContext.VO]
         * var barReference =
         * {
         *   base: fooContext.AO =&gt; null =&gt; global
         *   propertyName: 'bar'
         * }
         *  AO.bar is equivalent of null.bar
    
         /* Questions:
         * and what is different from case a ?
         */
    
         alert(this.x); // 10 - case d
        /* case d) I assume resolving x:
         * barContext.scope = [barContext.AO, fooContext.AO, globalContext.VO]
         * var xReference =
         * {
         *   base: null =&gt; global
         *   propertyName: 'x'
         * }
         *  calling GetValue we have the real value of x
         */
    
         /* Questions:
         *  if "Identifier resolution is a process of determination to which variable object in scope chain the variable (or the function declaration) belongs."
         *  if "The activation object always returns as this value — null"
         *  how a function declaration (calling ) or variable (resolving) belong to an AO instead of always global VO ?
         */
            }
         bar();
         }
         /* it seems AO is always null only in determine the this value ?, how ?
         */
         foo();
    
  34. @frankie TESta

    The this == null -> global in case of AO relates only to function calls (in order to determine which value the this will have at the activation).

    function foo() {
      function bar() {
        return this;
      }
      bar(); // AO.bar() -> null.bar() -> bar.call(global) -> global
    }

    And the identifier resolution process relates to referencing vars in a code. So, when we call bar() above, before it can be activated, the bar name should be resolved. And its resolution happens in fooContext.AO -> global chain (and is found directly in fooContext.AO).

    Notice, that this value does not participate in identifiers resolution process since it directly belongs to the context. So when we return this from bar, it means return barContext.this (and it’s set to the global object).

  35. I was confused by the following codes.

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

    How is the identifier–“foo”(an object) executed by the control?

    Does the bar(identifier) in last row of codes participate in identifiers resolution process?

  36. And resuming my last question,My firfox(27.0.1) displays “[object Object]”, not [object foo].

  37. @Drake

    Hey Drake,

    After I had a quick look of your question, your code would probably cause an error, and it won’t even execute.

    Notice the

    var foo() = {}
    

    hope you got it.

  38. Hi Dmitry,

    After reading this session, I still have following two questions? Please help. Thanks.

    The first one, in following excerption, why similar situation in “catch” object is recognized as a bug?

    “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. I.e. this value in the given activation should be set to global object, but not to catch object:”

    The second one, could you please give a more detail explanantion of the situation for recursive call of the named functions?

    (function foo(bar) {
     
      alert(this);
    
      !bar && foo(1); // "should" be special object, but always (correct) global
     
    })(); // global
    

    Regards.

  39. Hi Dmitry,

    I saw one example on “professional javascript”, while I cannot understand.

    Could you please give a description, why we can get each result? Thanks.

    In addition, could you please give their “VO”, “AO”, “[[Scope]]” and Scope values?

    —————————————

    var name = "The Window";
    
    var object = {
      name : "My Object",
      getNameFunc : function {
        return function () {
          return this.name;
        };
      }
    };
    
    alert(object.getNameFunc()()); // "This Window"

    —————————————

    Using one intermediate ‘that’, the result is its own name, not the global one, why?
    —————————————

    var name = "The Window";
    
    var object = {
      name : "My Object",
      getNameFunc : function () {
        vat that = this;
        return function () {
          return that.name;
        };
      }
    };
    
    alert(object.getNameFunc()()); // "My Object"

    —————————————

    Please help, waiting for your reply.

    Regards.

  40. @Hong

    why similar situation in “catch” object is recognized as a bug?

    Because simple function calls like `foo()` should set this value to global object in ES5. In ES3 it could be the catch-object.

    Could you please give a description, why we can get each result?

    As this article explains, the this value is not statically bound to a function by default. That is way, when you return a function, and execute it, you have this value as the global object (window), since you don’t have a reference value, but function value, when it’s returned (please re-read this chapter, it’s explained there).

    In the second call, the variable that is actually statically captured by closure, and is correctly accessible after the return. And its value is saved this.

  41. @Dmitry, thanks for your explanation.

    I still have some questions.

    Q.A, What is the difference b/w following two forms? Context & VO/AO difference?

    Could you please help list VO/AO of getNameFunc and that anonymous returned function??

    Form 1

    	var name = "The Window";
    	 
    	var object = {
    	  name : "My Object",
    	  getNameFunc : function () {
    	    return function () {
    	      return this.name;
    	    };
    	  }
    	};
    	 
    	alert(object.getNameFunc()()); // "This Window"

    Form 2

    	var name = "The Window";
    	 
    	var object = {
    	  name : "My Object",
    	  getNameFunc : function () {
    	    var foo = function () {
    	      return this.name;
    	    };
                return foo;
    	  }
    	};
    	 
    	alert(object.getNameFunc()()); // "This Window"

    Q.B Can we take the returned anonymous function as one inner funtion of getNameFunc? Thus, this inner function will be added into the AO of getNameFunc, so ‘this’ will resolved to global.

    Q.C in your comment about the second call with “var that=this;”, you said “the variable that is actually statically captured by closure, and is correctly accessible after the return”, statically captured? I think it is still dynamic, “var that=this;” is outside returned anonymous function, so base property of ‘this’ is just ‘object’ and ‘this’ is dynamically resolved to ‘object’, right?

    Q.D How to determine the ‘base’ property of one Reference type? Actually, I am not very clear about this “Reference Type” concept either, an abstract concept?

    Thanks very much, waitting for your reply:)

    Regards,
    Hong

  42. @Hong

    The Form 1 and Form 2 semantically do not differ: that you saved a function to the foo var in Form 2, doesn’t change this value at activation, it will be global object (window). The foo identifier is saved though in the second case in the scope chain of the returned function.

    Activation object (AO) is always created fresh for each function call. So when you call object.getNameFunc():

    Form 1

    getNameFunc.[[Scope]] = [{object: ..., name: 'The Window'}];
    getNameFuncContext.AO = {arguments: ...}; // empty
    

    Form 2

    getNameFunc.[[Scope]] = [{object: ..., name: 'The Window'}];
    getNameFuncContext.AO = {arguments: ..., foo: function};
    

    But when the returned function is called, its this value is set to global object.

    In your previous examples whether that was used, that var was captured in closure, and thus had access to the name property of the object.

    Q.C in your comment about the second call with “var that=this;”, you said “the variable that is actually statically captured by closure, and is correctly accessible after the return”, statically captured?

    By statically captured, I mean closured. I.e. the returned function has access to that, and the value of this on the time when getNameFunc is executed, and this value is the object.

    Q.D How to determine the ‘base’ property of one Reference type? Actually, I am not very clear about this “Reference Type” concept either, an abstract concept?

    Yes, please re-read this chapter, it explains the reference concept, and its base component. In the simplest case the base is what stands before the dot: foo.bar() — the base is foo here. The foo() is also reference, with empty base, that is set to global.