ECMA-262-3 in detail. Chapter 2. Variable object.

Read this article in: Russian, Chinese (version1, version2, version 3), Korean, German.

Always in programs we declare functions and variables which then successfully use building our systems. But how and where the interpreter finds our data (functions, variable)? What occurs, when we reference to needed objects?

Many ECMAScript programmers know that variables are closely related with the execution context:

var a = 10; // variable of the global context

(function () {
  var b = 20; // local variable of the function context
})();
 
alert(a); // 10
alert(b); // "b" is not defined
 

Also, many programmers know that the isolated scope in the current version of specification is created only by execution contexts with “function” code type. I.e., in contrast with C/C++, for example the block of for loop in ECMAScript does not create a local context:

for (var k in {a: 1, b: 2}) {
  alert(k);
}
 
alert(k); // variable "k" still in scope even the loop is finished

Let’s see in more details what occurs when we declare our data.

If variables are related with the execution context, it should know where its data are stored and how to get them. This mechanism is called a variable object.

A variable object (in abbreviated form — VO) is a special object related with an execution context and which stores:

  • variables (var, VariableDeclaration);
  • function declarations (FunctionDeclaration, in abbreviated form FD);
  • and function formal parameters

declared in the context.

Notice, in ES5 the concept of variable object is replaced with lexical environments model, which detailed description can be found in the appropriate chapter.

Schematically and for examples, it is possible to present variable object as a normal ECMAScript object:

VO = {};

And as we said, VO is a property of an execution context:

activeExecutionContext = {
  VO: {
    // context data (var, FD, function arguments)
  }
};

Indirect referencing to variables (via property names of VO) allows only variable object of the global context (where the global object is itself the variable object). For other contexts directly to reference the VO is not possible, it is purely mechanism of implementation.

When we declare a variable or a function, there is nothing else as creation of the new property of the VO with the name and value of our variable.

Example:

var a = 10;

function test(x) {
  var b = 20;
};

test(30);

And corresponding variable objects are:

// Variable object of the global context
VO(globalContext) = {
  a: 10,
  test: <reference to function>
};
 
// Variable object of the "test" function context
VO(test functionContext) = {
  x: 30,
  b: 20
};

But at implementation level (and specification) the variable object is an abstract essence. Physically, in concrete execution contexts, VO is named differently and has different initial structure.

Some operations (e.g. variable instantiation) and behavior of the variable object are common for all execution context types. From this viewpoint it is convenient to present the variable object as an abstract base thing. Function context can also define additional details related with the variable object.

AbstractVO (generic behavior of the variable instantiation process)

  ║
  ╠══> GlobalContextVO
  ║        (VO === this === global)
  ║
  ╚══> FunctionContextVO
           (VO === AO, <arguments> object and <formal parameters> are added)

Let’s consider it in detail.

Here, first it is necessary to give definition of the Global object.

Global object is the object which is created before entering any execution context; this object exists in the single copy, its properties are accessible from any place of the program, the life cycle of the global object ends with program end.

At creation the global object is initialized with such properties as Math, String, Date, parseInt etc., and also by additional objects among which can be the reference to the global object itself — for example, in BOM, window property of the global object refers to global object (however, not in all implementations):

global = {
  Math: <...>,
  String: <...>
  ...
  ...
  window: global
};
 

When referencing to properties of global object the prefix is usually omitted, because global object is not accessible directly by name. However, to get access to it is possible via this value in the global context, and also through recursive references to itself, for example window in BOM, therefore write simply:

String(10); // means global.String(10);

// with prefixes
window.a = 10; // === global.window.a = 10 === global.a = 10;
this.b = 20; // global.b = 20;

So, coming back to variable object of the global context — here variable object is the global object itself:

VO(globalContext) === global;

It is necessary to understand accurately this fact since for this reason declaring a variable in the global context, we have ability to reference it indirectly via property of the global object (for example when the variable name is unknown in advance):

var a = new String('test');

alert(a); // directly, is found in VO(globalContext): "test"

alert(window['a']); // indirectly via global === VO(globalContext): "test"
alert(a === this.a); // true
 
var aKey = 'a';
alert(window[aKey]); // indirectly, with dynamic property name: "test"
 

Regarding the execution context of functions — there VO is inaccessible directly, and its role plays so-called an activation object (in abbreviated form — AO).

VO(functionContext) === AO;

An activation object is created on entering the context of a function and initialized by property arguments which value is the Arguments object:

AO = {
  arguments: <ArgO>
};
 

Arguments object is a property of the activation object. It contains the following properties:

  • callee — the reference to the current function;
  • length — quantity of real passed arguments;
  • properties-indexes (integer, converted to string) which values are the values of function’s arguments (from left to right in the list of arguments). Quantity of these properties-indexes == arguments.length. Values of properties-indexes of the arguments object and present (really passed) formal parameters are shared.

Example:

function foo(x, y, z) {
 
  // quantity of defined function arguments (x, y, z)
  alert(foo.length); // 3

  // quantity of really passed arguments (only x, y)
  alert(arguments.length); // 2

  // reference of a function to itself
  alert(arguments.callee === foo); // true
 
  // parameters sharing

  alert(x === arguments[0]); // true
  alert(x); // 10
 
  arguments[0] = 20;
  alert(x); // 20
 
  x = 30;
  alert(arguments[0]); // 30
 
  // however, for not passed argument z,
  // related index-property of the arguments
  // object is not shared
 
  z = 40;
  alert(arguments[2]); // undefined
 
  arguments[2] = 50;
  alert(z); // 40
 
}
 
foo(10, 20);
 

Concerning the last case, in older versions of Google Chrome there was a bug — there parameter z and arguments[2] were also shared.

In ES5 the concept of activation object is also replaced with common and single model of lexical environments.

Now we have reached the main point of this article. Processing of the execution context code is divided on two basic stages:

  1. Entering the execution context;
  2. Code execution.

Modifications of the variable object are closely related with these two phases.

Notice, that processing of these two stages are the general behavior and independent from the type of the context (i.e. it is fair for both: global and function contexts).

On entering the execution context (but before the code execution), VO is filled with the following properties (they have already been described at the beginning):

  • for each formal parameter of a function (if we are in function execution context)
  • — a property of the variable object with a name and value of formal parameter is created; for not passed parameters — property of VO with a name of formal parameter and value undefined is created;

  • for each function declaration (FunctionDeclaration, FD)
  • — a property of the variable object with a name and value of a function-object is created; if the variable object already contains a property with the same name, replace its value and attributes;

  • for each variable declaration (var, VariableDeclaration)
  • — a property of the variable object with a variable name and value undefined is created; if the variable name is the same as a name of already declared formal parameter or a function, the variable declaration does not disturb the existing property.

Let’s see on the example:

function test(a, b) {
  var c = 10;
  function d() {}
  var e = function _e() {};
  (function x() {});
}
 
test(10); // call
 

On entering the test function context with the passed parameter 10, AO is the following:

AO(test) = {
  a: 10,
  b: undefined,
  c: undefined,
  d: <reference to FunctionDeclaration "d">
  e: undefined
};

Notice, that AO does not contain function x. This is because x is not a function declaration but the function-expression (FunctionExpression, in abbreviated form FE) which does not affect on VO.

However, function _e is also a function-expression, but as we will see below, because of assigning it to the variable e, it becomes accessible via the e name. The difference of a FunctionDeclaration from the FunctionExpression is in detail discussed in Chapter 5. Functions.

And after that there comes the second phase of processing of a context code — the code execution stage.

By this moment, AO/VO is already filled by properties (though, not all of them have the real values passed by us, most of them yet still have initial value undefined).

Considering all the same example, AO/VO during the code interpretation is modified as follows:

AO['c'] = 10;
AO['e'] = <reference to FunctionExpression "_e">;
 

Once again I notice that function expression _e is still in memory only because it is saved to declared variable e. But the function expression x is not in the AO/VO. If we try to call x function before or even after definition, we get an error: "x" is not defined. Unsaved to a variable function expression can be called only with its definition (in place) or recursively.

One more (classical) example:

alert(x); // function

var x = 10;
alert(x); // 10

x = 20;

function x() {}

alert(x); // 20
 

Why in the first alert x is a function and moreover is accessible before the declaration? Why it’s not 10 or 20? Because, according to the rule — VO is filled with function declarations on entering the context. Also, at the same phase, on entering the context, there is a variable declaration x, but as we mentioned above, the step of variable declarations semantically goes after function and formal parameters declarations and on this phase do not disturb the value of the already declared function or formal parameter with the same name. Therefore, on entering the context VO is filled as follows:

VO = {};
 
VO['x'] = <reference to FunctionDeclaration "x">
 
// found var x = 10;
// if function "x" would not be already defined 
// then "x" be undefined, but in our case
// variable declaration does not disturb
// the value of the function with the same name
 
VO['x'] = <the value is not disturbed, still function>
 

And then at code execution phase, VO is modified as follows:

VO['x'] = 10;
VO['x'] = 20;
 

what we can see in the second and third alerts.

In the example below we see again that variables are put into the VO on entering the context phase (so, the else block is never executed, but nevertheless, the variable b exists in VO):

if (true) {
  var a = 1;
} else {
  var b = 2;
}

alert(a); // 1
alert(b); // undefined, but not "b is not defined"
 

Often various articles and even books on JavaScript claim that: “it is possible to declare global variables using var keyword (in the global context) and without using var keyword (in any place)”. It is not so. Remember:

variables are declared only with using var keyword.

And assignments like:

 a = 10; 

just create the new property (but not the variable) of the global object. “Not the variable” is not in the sense that it cannot be changed, but “not the variable” in concept of variables in ECMAScript (which then also become properties of the global object because of VO(globalContext) === global, we remember, yeah?).

And the difference is the following (let’s show on the example):

alert(a); // undefined
alert(b); // "b" is not defined

b = 10;
var a = 20;
 

All again depends on VO and phases of its modifications (entering the context stage and the code execution stage):

Entering the context:

VO = {
  a: undefined
};
 

We see that at this phase there is no any b since it is not a variable, b will appear only at code execution phase (but in our case won’t since there is an error).

Let’s change the code:

alert(a); // undefined, we know why

b = 10;
alert(b); // 10, created at code execution

var a = 20;
alert(a); // 20, modified at code execution
 

There is one more important point concerning variables. Variables, in contrast with simple properties, have attribute {DontDelete}, meaning impossibility to remove a variable via the delete operator:

a = 10;
alert(window.a); // 10

alert(delete a); // true

alert(window.a); // undefined

var b = 20;
alert(window.b); // 20

alert(delete b); // false

alert(window.b); // still 20
 

Note, in ES5 {DontDelete} is renamed into the [[Configurable]] and can be manually managed via Object.defineProperty method.

However there is one execution context on which this rule does not affect. It is the eval context: there {DontDelete} attribute is not set for variables:

eval('var a = 10;');
alert(window.a); // 10

alert(delete a); // true

alert(window.a); // undefined

For those who test these examples in console of some debug tool, e.g. Firebug: notice, that Firebug also uses eval to execute your code from the console. So there vars also do not have {DontDelete} and can be deleted.

As it was already noted, by the standard, to get direct access to the activation object is impossible. However, in some implementations, namely in SpiderMonkey and Rhino, functions have special property __parent__, which is the reference to the activation object (or the global variable object) in which these functions have been created.

Example (SpiderMonkey, Rhino):

var global = this;
var a = 10;
 
function foo() {}
 
alert(foo.__parent__); // global
 
var VO = foo.__parent__;
 
alert(VO.a); // 10
alert(VO === global); // true
 

In the example above we see that function foo is created in the global context and, accordingly, its __parent__ property is set to variable object of the global context, i.e. to the global object.

However, to get the activation object in SpiderMonkey with the same way is not possible: depending on the version, __parent__ for inner function returns either null or global object.

In Rhino, access to the activation object is allowed and available via the same way:

Example (Rhino):

var global = this;
var x = 10;
 
(function foo() {
 
  var y = 20;
 
  // the activation object of the "foo" context
  var AO = (function () {}).__parent__;
 
  print(AO.y); // 20
 
  // __parent__ of the current activation
  // object is already the global object,
  // i.e. the special chain of variable objects is formed,
  // so-called, a scope chain
  print(AO.__parent__ === global); // true
 
  print(AO.__parent__.x); // 10
 
})();
 

In this article we have moved further forward in studying of objects related with execution contexts. I hope the material is useful and has clarified some aspects and ambiguities which, probably, you had before. Further by the plan, the next chapters will be devoted to the Scope chain, Identifier resolution and, as consequence, Closures.

If you have questions, feel free to ask them in comments.


Translated by: Dmitry A. Soshnikov.
Published on: 2010-03-15

Originally written by: Dmitry A. Soshnikov [ru, read »]
Originally published on: 2009-06-27

Tags: , , ,

 
 
 

69 Comments:

  1. Gravatar of qFox qFox
    15. March 2010 at 23:50

    Nice writeup. By VO you mean the Reference I assume?


  2. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    16. March 2010 at 14:29

    @qFox

    Nice writeup. By VO you mean the Reference I assume?

    Thanks; about VO — this is a just my abbreviation for “Variable object”; for shortness, not to repeat every time “variable object” phrase as there are to many in this text. Also, it is convenient to use in formulas and talks (e.g. saying that current scope chain is a VO|AO + [[Scope]] — which means, that variable/activation object is added in front of parent scope chain).

    About “Reference” — what exactly do you mean? Yes, it is a reference to object, but VO|AO — is a purely implementation mechanism; only VO of global context is accessible directly and as implementation feature — AO in Rhino. Or maybe you meant Reference type? If so, VO|AO can be used as a base property of Reference type value.

    Dmitry.


  3. Gravatar of Juan Anzaldo Juan Anzaldo
    17. March 2010 at 03:25

    excelent articles If you have in mind to translate in spanish maybe I can help

    thanks for the info


  4. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    17. March 2010 at 12:09

    @Juan Anzaldo

    excelent articles If you have in mind to translate in spanish maybe I can help

    Thanks, Juan. Yes, it is possible to translate it to Spanish (I’m glad to see that there are many Spanish guys interested deeply in ECMAScript). But unfortunately I don’t know Spanish at all. So if you take care about the English => Spanish translation, I’ll help with detailed explanations (or with clarifying of ambiguities) if will be needed.

    Dmitry.


  5. Gravatar of Alejandro Moreno Alejandro Moreno
    12. April 2010 at 20:50

    So that’s why vars should go at the beginning of scripts!

    These articles are awesome.


  6. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    12. April 2010 at 21:29

    @Alejandro Moreno

    So that’s why vars should go at the beginning of scripts!

    Yep, sometimes it is convenient to define all vars at the beginning, because anyway they all are parsed on entering the context.

    But for some vars it is also useful to declare them at the code position where they are used (e.g. loop counters) — just because it’s convenient and you don’t want to see all auxiliary helper variables at the beginning if e.g. you exit the code in the first line if some check isn’t passed. Although one should keep in mind that variable still will be available after the loop is finished.

    Dmitry.


  7. Gravatar of denisdeng denisdeng
    18. April 2010 at 17:26

    Good article,I have learned a lot form here. So I translate it into Chines:

    ECMA-262-3 深入解析.第二章.变量对象

    thank you!


  8. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    18. April 2010 at 17:35

    @denisdeng

    Thanks, that’s great. Added a link to your translation.


  9. Gravatar of denisdeng denisdeng
    18. April 2010 at 17:39

    Thank you! I will translate the next chapters as soon as possible。


  10. Gravatar of justin justin
    22. April 2010 at 09:30

    I have a question:
    “properties-indexes (integer, converted to string) “,
    I think you want to say:
    “properties-indexes [integer, converted to string]”

    it’s difference at “()” or “[]”
    Do you think my understanding correct?


  11. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    22. April 2010 at 12:09

    @justin

    I think you want to say:
    “properties-indexes [integer, converted to string]”

    it’s difference at “()” or “[]”

    Oh, nope, in that sentence was mentioned not a code expression, but just simple grammar punctuation. I notice there what exactly is an “index-property” (or “array-index” which is described in 15.4 of ES3 spec). Because ES3 has only properties and these properties can be only strings.

    I could change it to array indexes definition (because ES3 has such concept), but then arguments object could be treated as an array instance, but it is not (although, I think that it is an error of the spec and arguments should be an array).

    And “()” — was just a wording grammar punctuation there.

    Dmitry.


  12. Gravatar of justin justin
    22. April 2010 at 12:52

    I understand, thank you!

    Another problem:
    “It is convenient to present variable object as base abstract essence from which concrete sub essences playing role of variable object in different execution contexts are “inherited””

    This passage is not easy to understand, not easy to translate.
    Here is my translate:
    Chinese:
    变量对象作为基本抽象事物来表现是很方便的,具体子事物是抽象事物的具体实现,具体子事物在不同的执行上下文中扮演着变量对象的角色,它们是“可继承” 的;
    English:
    Variable objects to represent things as the basic abstraction is very convenient;
    Specific sub-things are abstract and concrete realization of things;
    Specific sub-things in a different execution context play the role of the variables object.

    For example:
    AO is VO’s concrete realization in function execution context;
    AO === Specific sub-things
    VO === the basic abstraction things

    Do you think my understanding correct?


  13. Gravatar of justin justin
    22. April 2010 at 12:55

    AO inherite form VO?


  14. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    22. April 2010 at 14:42

    @justin

    AO is VO’s concrete realization in function execution context;
    AO === Specific sub-things
    VO === the basic abstraction things

    Do you think my understanding correct?

    Yep, that exactly I meant. Yes, “inherited” word was a little confusing, so I removed it. Added an example illustration to make it easier to represent.

    AO inherite form VO?

    “Inherit” meant mostly that there is some common behavior (i.e. variable instantiation process) which is independent from the execution context type, but at the same time different execution context types can define their own initial structure of VO (e.g. arguments object and formal parameters of a function) and moreover, use different object as storage for variable instantiation: in global context — it is global object itself, in function context — it is an activation object.

    Dmitry.


  15. Gravatar of justin justin
    22. April 2010 at 19:36

    VO/AO,I understand that, thank you very muck!

    one more question:)

    ” but“not the variable” in concept of variables in ECMAScript“

    This passage is not easy to understand,I think your meant is :

    because it does not meet the concept of variable in ECMAScript standard, so it “is not a variable”

    Correct?


  16. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    22. April 2010 at 21:03

    @justing

    because it does not meet the concept of variable in ECMAScript standard, so it “is not a variable”

    Correct?

    Yep, correct. The main goal that variables in ECMAScript (1) cannot be deleted (except the eval context) with using of delete operator and (2) instantiated on entering the context. Exactly these two facts were meant in sentence “is a variable in concept of variables in ECMAScript”.

    Meanwhile, unqualified identifiers of the global object (i.e. simple assignment to non-existent yet identifier, such as: a = 10) — not: they can be deleted and created at code execution stage.

    Dmitry.


  17. Gravatar of justin justin
    23. April 2010 at 14:05

    Thanks so much, through this article I learned a lot!

    After disscussing with you,I think I have understood this article totally , and also translated it into Chinese .

    I’m sure my translation is more nearly to this excellent article.
    here it is : http://www.cnblogs.com/justinw/archive/2010/04/23/1718733.html


  18. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    23. April 2010 at 14:45

    @justin

    I’m sure my translation is more nearly to this excellent article.

    OK, I will add the second version of Chinese translation for this chapter. Also you can discuss it with Denis (which also provides translations) about this question. Because I, unfortunately, can’t say which Chinese translation is better (because don’t know Chinese at all) and automatic Google-translate also cannot provide such info for me.

    Dmitry.


  19. Gravatar of justin justin
    23. April 2010 at 15:24

    I understand, thanks!


  20. Gravatar of justin justin
    23. April 2010 at 15:33

    I have a suggestion
    If the article is updated, it is best to maintain an update log
    then facilitate future updates Other languages


  21. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    23. April 2010 at 17:12

    @justin

    I have a suggestion
    If the article is updated, it is best to maintain an update log
    then facilitate future updates Other languages

    In some other articles I would make something like “updated on <date>“. What actually I did in comments of e.g. The Quiz article when was changing some questions (because it was important for those who already passed the test with previous questions).

    But this series is academical so I don’t want to break article descriptions with some update, update, update words. It should be complete and up-to-date information without breaking the text itself.

    But for own purposes (and to keep translations also up-to-date) — yeah, I’ll think about it and maybe will make sort of subversion repository for that.

    Dmitry.


  22. Gravatar of sergeM sergeM
    17. September 2010 at 15:09

    Hi Dmitry,

    I have tested this following bit of code in the firebug console, in Google Chrome, and Firefox. The code works as expected in Chrome, but does not in firefox. This is because, executed in Firefox, the global object “window” is not equals to the context object “this”. Could you explain why ?

    Thanks,

    Serge.
    ————————————-

    var a = new String('test');
    alert(a); // directly, is found in VO(globalContext): "test"
    alert(window['a']); // indirectly via global === VO(globalContext): "test"
    alert(a === this.a); // true
    var aKey = 'a';
    alert(window[aKey]); // indirectly, with dynamic property name: "test"

  23. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    17. September 2010 at 17:18

    @sergeM

    This is because, executed in Firefox, the global object “window” is not equals to the context object “this”. Could you explain why ?

    Yes, exactly. Firebug evaluates its console’s code in several wrapper functions and applying with statement (where the argument of with statement is the _FirebugCommandLine object).

    You may check this by evaluating in Firebug’s console the following code:

    // to see which function
    // evaluates the code
    alert(arguments.callee);
    
    // a caller of the previous function
    alert(arguments.callee.caller);
    
    // in the first alert you'll find
    // (in current Firebug version) line
    // "var result = window.eval(expr);",
    // so you may check what is "expr"
    
    // and here you'll see this
    // "_FirebugCommandLine" object -
    // the argument of "with"
    alert(expr);
    
    // and exactly this object
    // is used as "this" value
    alert(this === _FirebugCommandLine); // true

    In contrast, Chrome’s console evaluates code in context of the global object, i.e. this value === global object.

    Though in versions of Firebug it’s should be fixed and this should be set to global object.

    Dmitry.


  24. Gravatar of sergeM sergeM
    21. September 2010 at 19:12

    Hello Dmitry, Thanks for your answer. By the way, your articles on ecmascript are an excellent and unique source to understand the intrinsics and subtilities of this language. Please, keep up the good work.

    Serge.


  25. Gravatar of Anderson Anderson
    5. October 2010 at 07:45

    Hello Dmitry,I’ve got a question here.As you mentioned in this article’s index:

    Variable object in different execution contexts
    Variable object in global context
    Variable object in function context

    Seems you didn’t explain what the variable object is like in a eval execution context.And in your another article Javascript.The Core,you said :

    Using eval we also enter a new (eval’s) execution context. However, eval uses either a global’s variable object, or a variable object of the caller (e.g. a function from which eval is called).

    Does that mean unlike global EC and function EC,a eval EC use its caller’s VO instead of creating its own VO?I’m confused and I will really appreciate it if you could give some more details on it.

    Thanks,
    Anderson.


  26. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    5. October 2010 at 22:33

    @Anderson

    Does that mean unlike global EC and function EC,a eval EC use its caller’s VO instead of creating its own VO?

    Yes, exactly. It is mentioned in the first chapter devoted to execution contexts. The same situation with the scope chain — eval borrows it from the calling context (i.e. context of the caller).

    Although, maybe I’ll add a small note to this chapter too (reminding it).

    Notice however, that it relates to ES3 and non-strict mode of the ES5. In the strict mode of the ES5, eval cannot create a variable/function in the caller’s context, since it evaluates in its sandbox environment.

    Dmitry.


  27. Gravatar of Richard Mallonee Richard Mallonee
    6. October 2010 at 17:06

    Hi Dmitry. Wonderful series of articles.
    The entire ECMAScript Language Specification ELS 262 Fifth edition is available, online, in linkable HTML form, at http://www.ecma262-5.com.

    Didn’t know if you were aware of this.

    -rm


  28. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    6. October 2010 at 18:05

    @Richard Mallonee

    Hi Richard,

    Yeah, I’m aware about this online version. I already use it in the ES5 series (in the section of additional literature). Your work is also very useful, thanks for sharing it online.

    However, it would be good to have there also links to all published erratas.

    Dmitry.


  29. Gravatar of nag nag
    16. October 2010 at 00:56

    Dmitry,

    Also, many programmers know that the isolated scope in the current version of specification is created only by execution contexts with “function” code type. I.e., in contrast with C/C++, for example the block of for loop in ECMAScript does not create a local context:

    for (var k in {a: 1, b: 2}) {  
      alert(k);  
    }  
    alert(k); // variable "k" still in scope even the loop is finished

    Let’s see in more details what occurs when we declare our data.

    What reasoning do you attribute to the variables declared within if-else, switch, for, do-while?
    I mean what is causing the variables declared within the above statements to attain global scope?

    Should a novice developer (like me) assume variables declared within control structures are like any other variables declared in global scope?

    thanks
    -nag


  30. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    16. October 2010 at 14:48

    @nag

    In some languages there is a block-scope variables. Such variables are being removed after the scope of block ends.

    For instance, in C:

    // global
    int foo = 10;
    
    if (true) {
      // local
      int foo = 20;
      printf("%d", foo); // 20
    } // block ends, its scope too, including local "foo"
    
    // again global
    printf("%d", foo); // 10

    In JavaScript (in current version of standard) there is no block-scope local variables; only — function-scope local variables.

    That means:

    // global
    var foo = 10;
    
    if (true) {
      var foo = 20;
      alert(foo); // 20
    } // block ends, but "foo" wasn't local
    
    alert(foo); // 20

    After careful reading of this chapter, you should know, that all variables are created on entering the context stage. This means, that second var in the JS example above is ignored, because there is already a “foo” var (notice, that if the local var in if-statement block was named e.g. “bar”, it also would created on entering the context). And only then, at code execution stage, there is just an assignment in the if-block to global “foo”.

    P.S.: actually, JS has some case of block-scope var, however, it’s not an explicit var, but the argument of the catch-clause:

    var foo = 10;

    try {
      throw 20; 
    } catch (foo) {
      alert(foo); // 20
    }
    
    // again global
    alert(foo); // 10

    Dmitry.


  31. Gravatar of nag nag
    16. October 2010 at 16:55

    Dimtry,

    I think catch() must be a type of function.
    I tried eval(), which treats local variables as belonging to global scope.

    Thank you very much for explaining in such a great detail.

    -nag


  32. Gravatar of nag nag
    16. October 2010 at 17:04

    Dmitry,
    Excerpt from your last comment::

    P.S.: actually, JS has some case of block-scope var, however, it’s not an explicit var, but the argument of the catch-clause:

    var foo = 10;
    try {
    throw 20;
    } catch (foo) {
    alert(foo); // 20
    }
    // again global
    alert(foo); // 10

    The scenario elucidated above holds good in firefox.
    IE treats foo as global.
    Thus the result of final alert(foo); statement is 20.

    -nag


  33. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    16. October 2010 at 19:11

    @nag

    I think catch() must be a type of function.

    No, it’s a clause of the try statement, it’s not a function. However, yeah, catch adds a special object, containing its argument (in this case — “foo”) in the front of current scope chain, shadowing a global “foo” Therefore, we can refer it during catch block is running. After it ends, its special object is removed from the scope chain and again the global “foo” is available. You can find this case described in detail in the fours chapter, devoted a scope chain.

    I tried eval(), which treats local variables as belonging to global scope.

    eval works with the calling context and uses the variable object and the scope chain exactly of the calling context (i.e. the context, from which eval is called). Therefore, if a variable is created within eval, it’s created in the calling context; and if you call eval from the global context, of course it creates a variable in the global context. This case is described in the first chapter.

    Notice however, that in the strict mode of ES5, eval executes its code in the sandbox environment and cannot create a variable in the calling context.

    IE treats foo as global.

    IE’s bug.

    Dmitry.


  34. Gravatar of nag nag
    18. October 2010 at 21:54

    thank you very much for such a detail elaboration.

    -nag


  35. Gravatar of Karl Oakes Karl Oakes
    3. December 2010 at 14:30

    Excellent article, I knew about variable and function hoisting but was unaware of their order within the VO. Great to read a series of articles that get down to the metal of the language, which helps to clarify some of the more intricate features.


  36. Gravatar of Luiz Luiz
    15. March 2011 at 19:09

    “Variables, in contrast with simple properties, have attribute {DontDelete}, meaning impossibility to remove property via the delete operator:”

    Looks like a typo error to me. Shouldn’t it be “impossibility to remove variable”?


  37. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    15. March 2011 at 20:13

    @Luiz

    Looks like a typo error to me. Shouldn’t it be “impossibility to remove variable”?

    Well, variables are also properties of something. This “something” is the variable/activation object. Attribute {DontDelete} relates exactly to a property, it’s the attribute of the property. So, it’s not a typo, since, repeat, a variable is also a property but with (initially) with its special attributes. However, to avoid confusion, yes, fixed it to “variable”; thanks.

    Dmitry.


  38. Gravatar of Plamen Todorov Plamen Todorov
    27. October 2011 at 04:12

    Dmitry, thanks for the great articles!

    You wrote:

    just create the new property (but not the variable) of the global object. “Not the variable” is not in the sense that it cannot be changed, but “not the variable” in concept of variables in ECMAScript

    In my view these variable-property discussions brings the most confusion among the developers.

    I would replace them with following:

    1. All we need is Data
    2. Data is accessed in two ways via Identifiers and via Properties (both of them of Reference Type you are talking about)
    3. JavaScript creates an identifier for each variable declaration, function declaration and function formal parameter. The identifiers are stored as properties in Variable Object. The identifiers could not be deleted.
    4. JavaScript creates a property for each property declaration. Two ways of doing it:
    -> p = 5, no var in front of it
    -> var obj = {p: 5}
    Properties does not affect the VO (except global properties, because VO === GO in Global Context). Properties could be deleted.

    To summarize: The less we use the term variable, the less is the confusion.

    I am curious, do you think such explanation is correct?
    May be a bit over-simplified considering EcmaScript specification but still…..

    //Plamen


  39. Gravatar of Dmitry A. Soshnikov Dmitry A. Soshnikov
    27. October 2011 at 21:08

    @Plamen Todorov

    To summarize: The less we use the term variable, the less is the confusion.

    I am curious, do you think such explanation is correct?

    Yes, it’s a good explanation. After all, all of them are just properties of something (either of a VO/AO, or an environment in ES5, or a simple object).

    Though, for simplicity a term variable in casual talks (when it’s not required to differentiate some deep details) of course can also be used.

    Dmitry.


  40. Gravatar of mark mark
    16. August 2012 at 02:42

    hi Dmitry, thanks 4 u great article

    just one thing i didn’t understand

    why a=10 create a property for global object? how?


  41. Gravatar of bird bird
    27. September 2012 at 02:35

    hi,Dmitry,you’ve shared a serial of posts for me.But I wonder that when a VO/AO destroy ?


  42. Gravatar of piglite piglite
    6. November 2012 at 01:02

    Hi,Dmitry!
    first of all, your article is really amazing, Keep Rocking! But, in this post, the paragraph “About variables”,you wrote as below:

    “variables are declared only with using var keyword.
    And assignments like:
    a = 10;
    just create the new property (but not the variable) of the global object.”

    The last sentence, to me, is not very clear. Your expression give me a feeling that in any case, useing assignment statement without var, should create a property of global.

    I think, a assignment statement without var should trigger a identifier looking-up follow the active context’s scope chain. When got the same property name in AO|VO, change that value, if got nothing, then create the new property of global with the name and value as the each side of =.

    all I said as the code at below:

    function foo(){
          var x=20;
          x=100;
          y=100;
          alert(x); //100
          alert(window.x); //undefined
          alert(y); //100
          alert(y===window.y); //true
    }
    foo();

    when foo function got execution, the vo(foo) had the x property, and vo(foo).x=20. The sentence x=100; just revised the vo(foo).x from 20 to 100, did not create the new property for global. But y, the new property of global was created.


  43. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    6. November 2012 at 11:51

    @piglite, yes, absolutely correct — the second use-case is meant here (when there is no yet such a variable).

    Before the assignment, the reference (on the left-hand side) should be resolved. And this is done at the identifiers resolution process through the scope chain.

    Notice also, that in strict mode such assignment already fails and doesn’t create a global property.


  44. Gravatar of 360weboy 360weboy
    1. January 2013 at 23:39

    Excellent!!! I strongly wish to translate your articles into Chinese. Could you allow me to do it?

    It is significant to the web developers in china because your great articles illustrate the truth of the concept in great details. It will be very helpful to the web developers in my country.

    Thanks in advance!


  45. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    2. January 2013 at 00:21

    @360weboy

    Thanks, glad it’s useful. Sure, send me the link when you’ll have the articles translated. Notice though, there are already Chinese translations of some chapters of the series.


  46. Gravatar of 360weboy 360weboy
    2. January 2013 at 01:23

    @Dmitry

    Hi,

    Okay. As soon as i have done it, i will send you the link. I noticed there is someone translate your articles. But, same great article may be translated differently depending on the understanding of the translator.

    Thanks a lot.


  47. Gravatar of Kuba Kuba
    1. December 2013 at 10:34

    Hi, Dmitry! First of all I would like to thank you very much for all that you have written there. It really improved my knowledge on ECMAScript and I think this is a valuable knowledge.

    But I’m writing it because there is still one thing that I don’t understand in ES – it’s the exact difference between ES3’s activation objects and ES5’s declarative environment records. I used to distinguish them by thinking that AOs are just normal, plain ECMAScript objects (what suggested that to me was that in the ES3 spec there is written that ‘arguments’ property of AO has the {DontEnum} attribute – exactly just like a regular object) but it was never said that AO is really a plain object. And, since you wrote that environment records are to REPLACE AOs I assume that there is some difference in those concepts. But I can’t find the differences. So: do they differ? If so, in what way? Curiosity is really killing me, even though ES3 is quite an old thing. Thanks in advance.


  48. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    4. December 2013 at 23:14

    @Kuba,

    The difference is mostly abstract. In ES5 spec, AO/VO are not distinguished in naming anymore, and combine into the concept of environments.

    How the environments are physically implemented is up to an implementation (i.e. it still can be a plain JS object). In practice though, engines likely use more optimized storage for declarative lexical environments, with e.g. faster access to variables, etc. Thus, it doesn’t cancel the fact, that the arguments is still {DonEnum} (or [[Enumerable]] == false in ES5 terms).

    So the changes to environments were in order to: (1) unify the concepts, and (2) allow implementations to make optimizations at implementing them.


  49. Gravatar of Kuba Kuba
    7. December 2013 at 08:31

    @Dmitry

    Much thansk for your response. You said, however, that environments were introduced to “allow implementations to make optimizations at implementing them.”. If I correctly understand that engines could implement AO/VO as whatever they wanted to (not necessarily as plain objects), and environments are also implemented that way, what omptimizations, that were unable to be done before, can be done now?


  50. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    7. December 2013 at 20:32

    @Kuba

    Correct. The optimization is one of the reasons. Another (and also important reason) is to abstract away the low-level concept of activation records (that are called as activation objects in ES), and instead to deal with highly-abstracted environments — without making a commitment how these environments are implemented (i.e. it’s still can be a plain JS object in some non-efficient, but fully spec-conformant, implementation, or vice-versa, a highly optimized low-level structure in a sophisticated compiler).

    As for whether such optimizations could be done before in ES3 — yes, they could actually (and were/are in practice) — as long as the implementation reflects to the user-level code what spec says. Even if it’s said that AO is a JS object, implementation could choose not to do this, if it’s not observable to the user-code.

    More detailed info can be found in the ES5.Ch3.1 Lexical Environments.


  51. Gravatar of Kuba Kuba
    8. December 2013 at 03:37

    @Dmitry

    Thanks for clarifying the topic for me :)

    More detailed info can be found in the ES5.Ch3.1 Lexical Environments.

    I have read it (along with all the other posts here – a few times, actually) but my doubts appeared after that. That’s why I decided to ask you directly. Thanks again.


  52. Gravatar of Amit Amit
    28. December 2013 at 21:05

    I was looking for some site where I can get topic wise JS tutorial. And here I am stopped for some time. I hope it’ll complete my search.


  53. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    29. December 2013 at 12:56

    @Amit, good overview, but please refer the original sources, since you’re using my abbreviations, and methodology.


  54. Gravatar of Hestroy Hestroy
    2. January 2014 at 03:49

    Thank you, Dmitry, very useful reading!


  55. Gravatar of Arun Arun
    19. February 2014 at 00:00

    Hi Dmitry. Great articles!

    I have a question.
    Assuming we are executing in global context, why is the below result like this?:

    alert(this.x);   //undefined
    alert(x);  //x is not defined

  56. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    22. February 2014 at 22:50

    @Arun, this is how resolution of identifiers and properties work: if an identifier cannot be resolved (is not found), an exception is thrown. However for a not found property, the default undefined value is returned.

    Details are here: http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain/ and http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/.


  57. Gravatar of Hong Hong
    18. July 2014 at 18:06

    Hi Dmitry,

    In your examples in “Entering the execution context”, since you mentioned, FD will be recorded ahead of variable declaration.

    So, whether it is better to update your case in following way? Switching the position of ‘c’ (variable declaration) and ‘d’ (function declaration), and put ‘d’ ahead of ‘c’ in AO(test).

    Please comment if I am wrong. Thanks.

    Your Code.
    ————————————–
    Let’s see on the example:

    	function test(a, b) {
    	  var c = 10;
    	  function d() {}
    	  var e = function _e() {};
    	  (function x() {});
    	}
    	  
    	test(10); // call

    On entering the test function context with the passed parameter 10, AO is the following:

    	AO(test) = {
    	  a: 10,
    	  b: undefined,
    	  c: undefined,
    	  d: function
    	  e: undefined
    	};

    ————————————–

    Regards :)


  58. Gravatar of Andreas Bolm Andreas Bolm
    19. July 2014 at 11:02

    Hello Dmitry,

    very nice article, I’ve translated this article to german, and I tend to translate, in my spare time, more of your ECMA articles to german.

    The link to my translation of your article
    ECMA-262:Kapitel 2. Variablenobjekt

    I’ve enhanced some aspects, mostly lingu-related, for better understanding, and I’ve tried to keep as close as possible to the original same time.

    If there is something you like to change pls. let me know.

    And if my article fits your requirements I would be lucky to a german ref-link at the top of your article.

    Greetings Andreas Bolm


  59. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    21. July 2014 at 22:45

    @Andreas Bolm, great, please add copyright notice on top of the translation with the link to this English version. Also, the signature at the bottom should contain the link to original Russian version for the “ru” link.


  60. Gravatar of Andreas Bolm Andreas Bolm
    24. July 2014 at 14:29

    @Dmitry Soshnikov

    All done Done. And I’ve put up another German translation of “JavaScript The Core”, this is because I got confused on some aspects of the (other) German translation, and some other minor translation issues.

    Therefore, here is my translation of “JavaScript The Core” ECMA-262: JavaScript Die Grundlagen

    If there is something you like to change pls. let me know.

    And if my (new) article fits your requirements I would be lucky to a german ref-link at the top of your article.

    You may splitt my comment to the appropriate article, if I’am doing something wrong here.


  61. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    24. July 2014 at 23:16

    @Andreas Bolm, OK, looks good, thanks, I’ll add the link to the translations soon.


  62. Gravatar of Andreas Bolm Andreas Bolm
    16. August 2014 at 04:47

    Hello Dmitry,

    I have a discussion at Stack Overflow on topic Multiple global objects in multiple HTML frames. Where some user states that the global object is not accsessible, and furthermore the Global VO does not exist, it merely should be a namespace, he says.

    He said: There is no [global] object: global scope is just a way of conveniently accessing the current window.

    But you said: Global object is the object which is created before entering any execution context; this object exists in the single copy

    So now I’m confused whether there is a Global VO or not?


  63. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    16. August 2014 at 16:56

    @Andreas Bolm

    So now I’m confused

    I’m not sure why are use confused :) as well as I’m not sure where the author of that comment refers to. Information on this blog refers to the official ECMAScript specification.


  64. Gravatar of Andreas Bolm Andreas Bolm
    18. August 2014 at 10:25

    @Dmitry Soshnikov

    Thank you for your time to answer. I came up with the idea that a global object must exist (in ECMA-based JavaScript), by translating your article ECMA-262:JavaScript the Core. Where section “Variable object” read this:

    “Variable object is an abstract concept. In different context types, physically, it’s presented using different object. For example, in the global context the variable object is the global object itself (that’s why we have an ability to refer global variables via property names of the global object).”

    The sentence “…in the global context the variable object is the global object itself…” brought me to this conclusion, albeit the leading sentence says: “Variable object is an abstract concept.” leads to quite the opposite. But collected together the information given here in this article and the other one mentioned, it already brought me back to this conclusion again. Thank you for your precious time.


  65. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    18. August 2014 at 14:44

    @Andreas Bolm, yes, information on this site reflects the actual specification, that defines the global object: http://es5.github.io/#x15.1.


  66. Gravatar of Hong Hong
    23. November 2014 at 03:26

    @Dmitry

    I come again, one more question, please help :)

    For the given example in the Code execution

    alert(x); // function

    var x = 10;
    alert(x); // 10

    x = 20;

    function x() {}

    alert(x); // 20


    VO = {};

    VO[‘x’] = <reference to FunctionDeclaration “x”>

    // found var x = 10;
    // if function “x” would not be already defined
    // then “x” be undefined, but in our case
    // variable declaration does not disturb
    // the value of the function with the same name

    VO[‘x’] = <the value is not disturbed, still function>

    I am confusing why VO['x'] = <reference to FunctionDeclaration "x"> ahead of VO['x'] = <the value is not disturbed, still function>
    .

    Doesn’t the JS interpreter scan the source code from up to bottom? Firstly, it encounters var x = 10;, and VO['x'] after assignment is VO['x'] = undefined, which means encountering one variable. Then, interpreter encounters function x() {}, and finds that x is already in VO, while this new one is a function declaration, and it will overwrite previous existing property and value with the same name, thus after assignment, VO is updated to VO['x'] = <reference to FunctionDeclaration "x">.

    Based on your interpretation, it seems interpreter needs scan source code more times.

    Does my understanding right? could you please give more explanation? Thanks.

    Regards :)


  67. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    24. November 2014 at 20:23

    @Hong, as Variable Instantiation of ES3 spec states, first go parameters, then function declarations, then variables.

    On entering the context, interpreter already has all information which function declarations and variables are defined in the function (from the parsing stage). So it goes and creates functions, then vars names.

    And then it starts execute the code, where assignments happen.


  68. Gravatar of Hong Hong
    24. November 2014 at 21:24

    @Dmitry, thanks for your explanation.

    It is now clear that when a declared variable has the same name as a declared function or formal parameter, the variable declaration does not disturb the existing property. How is following situation, when the function declaration has the same name as formal parameter? Will the declared function disturb (overwrite) the existing property added by formal parameter?


  69. Gravatar of Dmitry Soshnikov Dmitry Soshnikov
    25. November 2014 at 11:42

    @Hong, if you take a look at the Variable Instantiation spec, it says:

    If the variable object already has a property with this name, replace its value and attributes. Semantically, this step must follow the creation of FormalParameterList properties

    I.e. function declarations replace formals which were added first. Then the last stage are vars, which don’t replace function declarations:

    If there is already a property of the variable object with the name of a declared variable, the value of the property and its attributes are not changed. Semantically, this step must follow the creation of the FormalParameterList and FunctionDeclaration properties


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>