javascript
1月8日学习内容整理:JS的作用域和作用域链
補充:
對于編譯型語言,是編譯一次生成可執行文件來執行多次;對于解釋型語言,始終都是編譯一次執行一次
python編譯時要看有沒有賦值操作,沒有的話就不編譯任何內容;若有賦值操作,才會開辟內存空間,把變量指向這個內存空間,python執行時才會真正完成賦值操作,將這個值存放在編譯時開辟的內存地址空間里,變量指向這個地址空間,這就完成了一次賦值的編譯執行操作
這里所說的變量也包括函數名,對于定義函數,js編譯時會把名字直接指向function的地址,
?
作用域就是變量與函數的可訪問范圍,即作用域控制著變量與函數的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。
?
一、全局作用域
1、在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說一下幾種情形擁有全局作用域:
其實js的作用域和python的基本相同,我們可以按照python作用域對js變量進行分析,但要注意if 和 ?for沒有自己的作用域,
var ?x ?這只是聲明變量,編譯時也開辟內存空間,執行時js會默認把值設為undefined,若是python的話執行時就直接報錯了,因為編譯時沒有賦值操作也就不會開辟內存空間
var ?x=10 ? 這是既聲明又賦值,并且要注意的是下面的第2點,沒有var聲明的變量js會自動設置為全局變量
(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 definedfoo(); // 23inner(); // Uncaught ReferenceError: inner is not defined?
(2)所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:
var name="yuan";function foo(){age=23;var sex="male"}foo();console.log(age); // 23console.log(sex); // sex is not defined?
(3)所有window對象的屬性擁有全局作用域
一般情況下,window對象的內置屬性都都擁有全局作用域,例如window.alert()、window.location、window.top等等。
?
二、局部作用域
和全局作用域相反,局部作用域一般只在固定的代碼片段內可訪問到,最常見的例如函數內部,所有在一些地方也會看到有人把這種作用域成為函數作用域.
?
三、作用域鏈
在JavaScript中,函數也是對象,實際上,JavaScript里一切都是對象。函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問。
//-----**********************例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這部操作是在詞法分析時,即運行前完成的。?
轉載于:https://www.cnblogs.com/wanghl1011/articles/8242956.html
總結
以上是生活随笔為你收集整理的1月8日学习内容整理:JS的作用域和作用域链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Regex pattern in ope
- 下一篇: CommonJS/AMD/CMD/UMD