JavaScript基礎(chǔ)之?dāng)U展

js擴(kuò)展

js的作用域

作用域是JavaScript最重要的概念之一,想要學(xué)好JavaScript就需要理解JavaScript作用域和作用域鏈的工作原理。

任何程序設(shè)計語言都有作用域的概念,簡單的說,作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。

1. 全局作用域(Global Scope)

在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說一下幾種情形擁有全局作用域:

(1)最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域

var name="yuan";

function foo(){
  var age=23;
  function inner(){
    console.log(age);
  }
  inner();
}

console.log(name);    // yuan
//console.log(age);   // Uncaught ReferenceError: age is not defined
foo();                // 23
inner();              // Uncaught ReferenceError: inner is not defined

(2)所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:

var name="yuan";

function foo(){
    age=23;
    var sex="male"
}
foo();
console.log(age);   //  23
console.log(sex);   // sex is not defined

變量blog擁有全局作用域,而sex在函數(shù)外部無法訪問到。

(3)所有window對象的屬性擁有全局作用域

一般情況下,window對象的內(nèi)置屬性都都擁有全局作用域,例如window.alert()、window.location、window.top等等。

2. 局部作用域(Local Scope)

和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的例如函數(shù)內(nèi)部,所有在一些地方也會看到有人把這種作用域成為函數(shù)作用域.

如示例1中的age與inner都只有局部作用域。(js中if、for沒有自己的作用域)

作用域鏈(Scope Chain)

在JavaScript中,函數(shù)也是對象,實(shí)際上,JavaScript里一切都是對象。函數(shù)對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內(nèi)部屬性。其中一個內(nèi)部屬性是[[Scope]],由ECMA-262標(biāo)準(zhǔn)第三版定義,該內(nèi)部屬性包含了函數(shù)被創(chuàng)建的作用域中對象的集合,這個集合被稱為函數(shù)的作用域鏈,它決定了哪些數(shù)據(jù)能被函數(shù)訪問。

示例演示

//-----**********************例1*********************************

var s=12;
    function f(){
        console.log(s);
         var s=12;          // if s=12
        console.log(s)
    }
    f();

//-----**********************例2*********************************

var s=10;
function foo(){
  console.log(s);
  var s=5;
  console.log(s);
  function s(){console.log("ok")}// 函數(shù)的定于或聲明是在詞法分析時完成的,執(zhí)行時已不再有任何操作

  console.log(s);
}

foo();

//-----***********************例3********************************

function bar(age) {

        console.log(age);
        var age = 99;
        var sex= 'male';
        console.log(age);
        function age() {
            alert(123)
        };
        console.log(age);
        return 100;
}

result=bar(5);

//-----********************************************************

結(jié)果分析

我相信大家一定會有想不到的結(jié)果,接下來我們就以最復(fù)雜的例3來分析整個過程。

當(dāng)一個函數(shù)創(chuàng)建后,它的作用域鏈會被創(chuàng)建此函數(shù)的作用域中可訪問的數(shù)據(jù)對象填充。在函數(shù)bar創(chuàng)建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量,如下圖所示:

img

解析到函數(shù)調(diào)用時,即bar(5),會生成一個active object的對象,該對象包含了函數(shù)的所有局部變量、命名參數(shù)、參數(shù)集合以及this,然后此對象會被推入作用域鏈的前端,當(dāng)運(yùn)行期上下文被銷毀,活動對象也隨之銷毀。新的作用域鏈如下圖所示:

img

過程解析:

function bar(age) {

        console.log(age);
        var age = 99;
        var sex="male";
        console.log(age);
        function age(){
            alert(123);
        } ;
        console.log(age);
        return 100;
}

result=bar(5);

一 詞法分析過程(涉及參數(shù),局部變量聲明,函數(shù)聲明表達(dá)式):
    1-1 、分析參數(shù),有一個參數(shù),形成一個 AO.age=undefine;
    1-2 、接收參數(shù) AO.age=5;
    1-3 、分析變量聲明,有一個 var age, 發(fā)現(xiàn) AO 上面有一個 AO.age ,則不做任何處理
    1-4 、分析變量聲明,有一個 var sex,形成一個 AO.sex=undefine;
    1-5 、分析函數(shù)聲明,有一個 function age(){} 聲明, 則把原有的 age 覆蓋成 AO.age=function(){};
二 執(zhí)行過程:
    2-1 、執(zhí)行第一個 console.log(age) 時,當(dāng)前的 AO.age 是一個函數(shù),所以輸出的一個函數(shù)
    2-2 、這句 var age=99; 是對不 AO.age 的屬性賦值, AO.age=99 ,所以在第二個輸出的age是 99;
    2-3 、同理第三個輸出的是 99, 因?yàn)橹虚g沒有改變 age 值的語句了。

          注意:執(zhí)行階段:
                        function age(){
                            alert(123)
                        };

            不進(jìn)行任何操作,將執(zhí)行語句復(fù)制給age這部操作是在詞法分析時,即運(yùn)行前完成的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容