Navigate with keyboard arrows in all directions.
Use the control on the bottom right part as page availability hint.
You use variables as symbolic names for values in your application. The names of variables, called identifiers, conform to certain rules.
var obj = {prop: ‘propValue’};
The only way to create data is with:
var Object = function () { this.prop = "propValue"; }; var obj = new Object(); assertEquals("propValue", obj.prop);
Always think to what your identifier is pointing to!
In our example 'Object' identifier points to different function not the built-in provided by JavaScript
//Scope = VO.scopeArray var x = 10, y = 10; with( { x : 20 } ) { //Scope = withObject + VO.scopeArray assertEquals(x, 20); assertEquals(y, 10); var x = 30, y = 30; assertEquals(x, 30); assertEquals(y, 30); } //Scope = VO.scopeArray assertEquals(x, 10); assertEquals(y, 30);
try { ... } catch (ex) { //Scope = catchObject + VO.scopeArray alert(ex); } A catch clause creates temporary scope object with single property. var catchObject = { ex: {exception object} };
alert(p); // ? var p = 5; alert(p); // ? var p = 6; alert(p); // ?
alert(p); // undefined var p = 5; alert(p); // 5 var p = 6; alert(p); // 6
All declarations are moved (hoisted) on top of the context
With other words: All identifiers are created during context creation
alert(typeof x); // ? var x = 10; alert(x); // ? x = 20; function x() {}; alert(x); //?
alert(typeof x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); // 20
Identifiers created as a result of function declaration gets their values at context creation phase
function test() { foo(); // ? bar(); // ? var foo = function () { alert("foo"); }; function bar() { alert("bar"); } } test();
function test() { foo(); // TypeError "foo is not a function" bar(); // "bar" var foo = function () { //FE alert("foo"); }; function bar() { // FD alert("bar"); } } test();
Make difference between Function Declarations and Function Expressions
Identifiers that points to functions created with expression gets their value at Context Execution Phase
Defines a function as a part of a larger expression syntax (typically a variable assignment, callback etc.):
var f = function() {};
Anonymous FE does not introduce identifier because they do not have name!
Named FE introduce identifier visible only in the context created by NFE itself
var test = function test1() { //test1 is valid identifier here }; //test is valid identifier here //test1 is NOT valid identifier here
In Some IE versions test1 could be leaked into the parent context
Best Practice: var f = function f() {};
var x = 10; function foo() { var x = 20; var y = 30; var foo = function () {alert(x); alert(y);}; var bar = new Function('alert(x); alert(y);'); foo(); //20, 30 bar(); // 10, "y" is not defined }
var y = 100; function f() { var y = 10; alert(y); } f(); //10 alert(y); //100
var y = 100; eval('var y = 10; alert(y)'); //10 alert(y); //10
Eval Creates New Execution Context
Eval Augments The Calling Context
In the strict-mode of ES5, eval already does not influence the calling context, but instead evaluates the code in the local sandbox.
So if you completely understand the [[Scope]] and a scope chain topics, which in detail were discussed in the chapter 4, the question on understanding closures in ECMAScript will disappear by itself.
the anonymous function is funarg
exampleFunc -> Higher Order Function
function exampleFunc(funArg) { funArg(); } exampleFunc( function () { alert('funArg'); } );
(function functionValued() { return function () { alert('returned function is called'); }; })()();
In EcmaScript all functions are first class
var firstClosure; var secondClosure; function foo() { var x = 1; firstClosure = function () { return ++x; }; secondClosure = function () { return --x; }; x = 2; alert(firstClosure()); // 3 } foo(); alert(firstClosure()); // 4 alert(secondClosure()); // 3
All functions, independently from their type - function expression (anonymous, named) or function declaration - are closures!
Exception is Function created with Function constructor which scope contain only global object
From the practical viewpoint those functions are interesting which are:
1. passed as arguments and uses free variables
2. returned inner function (continue to exist after their parent context is finished)
Clone the object it points to
Change the pointer value
Proceed with mutation
There is no way to modify a string
str.concat('modification') doesn’t modify str at all, it returns a new string with the replacement executed.
var o = { x: 1 }; delete o.x; // true o.x; // undefined
var x = 1; delete x; // false x; // 1
function x(){} delete x; // false typeof x; // "function"
Identifiers (indirect property creation):
Properties(direct creation):
ReadOnly
DontEnum
Internal
DontDelete
- Identifiers have DontDelete property set to true
- Properties have DontDelete property set to false
var o = { x: 1 }; delete o.x; // true -> x is property and its 'DontDelete' property is false o.x; // undefined
var x = 1; delete x; // false -> x is identifier and its 'DontDelete' property is true x; // 1
function x(){} delete x; // false -> x is identifier and its 'DontDelete' property is true typeof x; // "function"
var x = 1; delete x; // true x; // undefined
- Firebug execute the code in Eval statement
- Declarations inside eval does not set DonDelete to true
Identifier (Data) Resolution:
- Search in: own AO, parents AO, GO, GO.prototype
//Yes it is searching in GO.prototype as well function foo() { alert(x); } Object.prototype.x = 10; foo(); // 10
Property (Nested Data) Resolution: