2015-02-01

Scope

In javaScript, scope is the context in which code is executed.Typically, scope is used to define the extent of information hiding—that is, the visibility(可见性) or accessibility(可访问性) of variables from different parts of the program.

  • Global Scope
  • Function Scope
  • Block Scope
  • Lexical Scope
  • Dynamic Scope

Global Scope

The global scope is the last stop in the scope chain . Therefore, variables defined in the global scope can be accessed from anywhere . Danger is that any piece of code can change global variables for any reason at any time.

// g1 be created in global scope
var g1 = 123; 

// global scope
(function() {
    // g be created in global scope
    g2 = 123; 
})();

变量声明不推荐lack var。缺少var的变量被称为implied globalsimplied globals会污染全局环境、导致代码很难管理.

Function Scope

Any variable which is defined within a function is visible within that entire function,not accessible outside of function

Function内部定义变量仅内部可见,可借助closure feature提供公共对外访问入口。类比java通过private隐藏变量、通过public提供公共对外访问入口。

function foo(){
    // private 
    var name ="dongc";

    return {
        // public entrance
        getName:function(){
            return name;
        }
    }
}

Block Scope

In theory, any variable is defined in block which is limited by the block({curly braces}). But current version of ECMAScript does not support block-level scope.

var x =10;
if(true){
    var x =20;
    console.log("inner:"+x);
}
console.log("outer:"+x);

However, some implementations (e.g. SpiderMonkey since 1.7 version) support alternative let instruction which allows the block-level scope. This instruction will be standardize in the future ES6 version:

let x = 10;
if (true) {
    let x = 20;
    console.log(x); // 20
}
console.log(x); // 10
Instruction **let** though is a syntactic sugar for the construction which may be implemented in the **ES3** version. The example above desugars to the following code: 将第二个变量"x"藏匿于Function Content内,避免污染外部环境(Global Content).
var x = 10;
if (true) {
    (function(x) {
        console.log(x); // 20
    })(20);
}
console.log(x); // 10

Lexical (Static) Scope

In static scoping, an identifier refers to its nearest lexical environment. The word “lexical” in this case relates to a property of a program text. I.e. where lexically in the source text a variable appears (that is, the exact place in the code) — in that scope it will be resolved later at runtime on referencing this variable. The word “environment” implies again something that lexically surrounds the definition.

通俗说: Lexical Scope是Function的”出生环境“。作为Function的静态属性([[scope]])存在,伴随一生。Lexical Scope在”出生时“就被确定。

// 全局环境 中国
function jiangsu(){ //江苏
    function suqian(){ //宿迁
        function shuyang(){ //沭阳
            function dongc(){ // dongc
            }
        }
    }   
}

出生地(dongc) =[沭阳县 宿迁市 江苏省 中国]

Function(dongc).[[scope]] =[shuyang,suqian,jiangsu,china]

Dynamic Scope

In Execution Phase,This is most often determined by how a function is invoked.

函数的调用者(this)在函数执行阶段才被指定。

When a function is called as a method of an object, this is set to the object the method is called on.

When called as an unbound function, this will default to the global context or window object in the browser. However, if the function is executed in strict mode, the context will default to undefined.

function foo(){
    console.log("invoker is :%o",this);
};
foo();
// invoker is :Window
var obj =new Object(); obj["name"] ="dongc"; obj["foo"] =foo; obj.foo(); // invoker is :Object
function foo1(){ "use strict" console.log("invoker is :%o",this); }; foo1() ; // invoker is :undefined
// dynamically bind this foo.call(obj); foo.apply(obj);

其次,可以通过调用callapply函数,动态指定当前执行对象(this)。