標籤:域控 ges 語言 執行 賦值 自己 tle try 生命週期
js的範圍
範圍是JavaScript最重要的概念之一,想要學好JavaScript就需要理解JavaScript範圍和範圍鏈的工作原理。
任何程式設計語言都有範圍的概念,簡單的說,範圍就是變數與函數的可存取範圍,即範圍控制著變數與函數的可見度和生命週期。在JavaScript中,變數的範圍有全域範圍和局部範圍兩種。
範圍
1. 全域範圍(Global Scope)
在代碼中任何地方都能訪問到的對象擁有全域範圍,一般來說一下幾種情形擁有全域範圍:
(1)最外層函數和在最外層函數外面定義的變數擁有全域範圍
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在函數外部無法訪問到。
(3)所有window對象的屬性擁有全域範圍
一般情況下,window對象的內建屬性都都擁有全域範圍,例如window.alert()、window.location、window.top等等。
2. 局部範圍(Local Scope)
和全域範圍相反,局部範圍一般只在固定的程式碼片段內可訪問到,最常見的例如函數內部,所有在一些地方也會看到有人把這種範圍成為函數範圍.
如樣本1中的age與inner都只有局部範圍。(js中if、for沒有自己的範圍)
範圍鏈(Scope Chain)
在JavaScript中,函數也是對象,實際上,JavaScript裡一切都是對象。函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被建立的範圍中對象的集合,這個集合被稱為函數的範圍鏈,它決定了哪些資料能被函數訪問。
樣本示範
please have a try:
//-----**********************例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")}// 函數的定於或聲明是在詞法分析時完成的,執行時已不再有任何操作 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);//-----********************************************************
結果分析
我相信大家一定會有想不到的結果,接下來我們就以最複雜的例3來分析整個過程。
當一個函數建立後,它的範圍鏈會被建立此函數的範圍中可訪問的資料對象填充。在函數bar建立時,它的範圍鏈中會填入一個全域對象,該全域對象包含了所有全域變數,如所示:
解析到函數調用時,即bar(5),會產生一個active object的對象,該對象包含了函數的所有局部變數、具名引數、參數集合以及this,然後此對象會被推入範圍鏈的前端,當運行期上下文被銷毀,使用中的物件也隨之銷毀。新的範圍鏈如所示:
過程解析:
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);一 詞法分析過程(涉及參數,局部變數聲明,函式宣告運算式): 1-1 、分析參數,有一個參數,形成一個 AO.age=undefine; 1-2 、接收參數 AO.age=5; 1-3 、分析變數聲明,有一個 var age, 發現 AO 上面有一個 AO.age ,則不做任何處理 1-4 、分析變數聲明,有一個 var sex,形成一個 AO.sex=undefine; 1-5 、分析函式宣告,有一個 function age(){} 聲明, 則把原有的 age 覆蓋成 AO.age=function(){};二 執行過程: 2-1 、執行第一個 console.log(age) 時,當前的 AO.age 是一個函數,所以輸出的一個函數 2-2 、這句 var age=99; 是對不 AO.age 的屬性賦值, AO.age=99 ,所以在第二個輸出的age是 99; 2-3 、同理第三個輸出的是 99, 因為中間沒有改變 age 值的語句了。 注意:執行階段: function age(){ alert(123) } ; 不進行任何操作,將執行語句複製給age這部操作是在詞法分析時,即運行前完成的。
前端之JS(五)