天天看點

Javascript中的作用域(scope)

類 C 語言一般都用于塊級作用域,但是Javascript中的 while, if-else, for, switch-case 等控制結構不具有自己的作用域,

在Javascript中隻有函數(function)具有自己的作用域,請比較如下的 C# 代碼和 Javascript 代碼:

//  C# 中 for 循環有自己的作用域

for  ( int  i  =   0 ; i  <   5 ; i ++ )

{

     //

}

Console.WriteLine(i);  //  目前上下文中不存在名稱“i”

//  Javascript中 for 循環沒有自己的作用域

for  ( var  i  =   0 ; i  <   5 ; i ++ ) {

     //  do something

}

console.log(i);    //  5

但是,Javascript中的函數有自己的作用域,如下示例:

//  function 擁有自己的作用域

( function () {

     var  j  =   6 ;

})();

console.log( typeof  (j));  //  'undefined'

//  function 中使用和全局變量相同名稱的局部變量

var  i  =   5 ;

( function () {

     var  i  =   1 ;

})();

console.log(i);    //  5

在函數中不使用 var 關鍵字聲明的變量,就會在全局範圍内查找,如下:

var  i  =   5 ;

( function () {

    i ++ ;     //  此時的i是全局變量

})();

console.log(i);    //  6

這裡就有一個可能讓人迷惑的代碼,如下:

var  i  =   6 ;

( function () {

    i ++ ;     //  此時的i是局部變量,但是未定義(undefined),undefined + 1 == NaN

    console.log(isNaN(i));     //  true

     var  i;

})();

console.log(i);    //  6

或許你會覺得函數中 i++, 引用的豈不是全部變量?

答案是否定的,隻要在函數内擁有相同名稱的局部變量定義,那這個變量就是局部的。

那我們如何在函數内引用和局部變量相同名稱的全局變量呢?

答案是使用命名字首。考慮如下代碼:

var  i  =   6 ;

( function () {

    window.i ++ ;     //  此時的i是局部變量

     var  i  =   1 ;

})();

console.log(i);    //  7

正因為自執行的匿名函數,可以用來向外部隐藏屬性,我們可以用這個特性在Javascript中實作私有屬性。

考慮如下擷取随機數([0,10])的對象:

var  random1  =  {

    _num:  - 1 ,

    _init:  function () {

         //  随機一個大于等于0,小于等于10的整數

         this ._num  =  Math.round(Math.random()  *   10 );

    },

    getNum:  function () {

         if  ( this ._num  ===   - 1 ) {

             this ._init();

        }

         return   this ._num;

    }

};

console.log( ' random1._num ==  '   +  random1._num);  //  -1

console.log( ' random1.getNum() ==  '   +  random1.getNum());  //  [0,10]

雖然我們的意圖是想向外界隐藏 _num 變量和 _init 屬性,不過這個目的顯然沒有達到,使用者仍然可以通過 random1._init(); 的方式調用。

我們需要是用Javascript中函數特有的性質(擁有自己的作用域),使用自執行的匿名函數來達到隐藏屬性的目的。

考慮如下解決辦法:

var  random2  =  {};

( function () {

     var  _num  =   - 1 ;

     function  _init() {

        _num  =  Math.round(Math.random()  *   10 );

    }

    random2.getNum  =   function () {

         if  (_num  ===   - 1 ) {

            _init();

        }

         return  _num;

    };

})();

console.log( ' random2._num ==  '   +  random2._num);  //  'undefined'

console.log( ' random2.getNum() ==  '   +  random2.getNum());  //  [0,10]

代碼下載下傳

繼續閱讀