javascript
[JavaScript] JavaScript作用域深度解析
JavaScript作用域
JavaScript中的函數運行在它們被定義的作用域里,而不是它們被執行的作用域里.
—— JS權威指南
在JS里,一切皆對象,函數也是。
一、有什么用
什么時候會用到它?它的存在有什么意義?這是我在學習一個新知識的時候首先發起的疑問。那么,在JavaScript里,作用域有什么用?
作用域規定了變量和函數的可訪問范圍,這個可訪問范圍可以細分為兩個場景:變量和函數的可見性和生命周期。
- 可見性:當訪問某個變量的時候,訪問的是局部變量還是全局變量?重復命名了多個變量,到底訪問的是哪個值?這個變量現在能不能用,為什么有時候會返回undefined?
- 生命周期:變量是一直存在在內存中么?什么時候會被銷毀?比如定義在函數內部的變量被稱為局部變量,這個變量只存在函數內部,函數調用后將會被銷毀,等等...當然如果有閉包什么的就要另當別論,在這里只討論最一般的情況。
二、全局作用域 & 局部作用域
//函數一 var authorName = "jennifer";function doSomething() {anotherName = "james";var blogName = "smoothlily";function innerSay() {alert(blogName);}innerSay(); }console.log(authorName); //jennifer doSomething(); //smoothlily console.log(anotherName); //james console.log(blogName); //腳本錯誤 innerSay(); //腳本錯誤針對可見性這個問題,可以聊一聊JS中規定的兩個作用域:全局作用域,局部作用域。
- 全局作用域(Global Scope)
在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說以下幾種情形擁有全局作用域:
最外層函數和在最外層函數外面定義的變量擁有全局作用域:
如函數一的變量authorName。
所有未定義直接賦值的變量自動聲明為擁有全局作用域:
如函數一的anotherName。
這種情況在寫代碼時最好不要出現,想要擁有全局作用域的變量還是乖乖的在腳本最開始顯性聲明全局變量。
所有window對象的屬性擁有全局作用域,例如window.name、window.location、window.top等等
- 局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代碼片段內可訪問到,最常見的就是函數內部:如函數一的blogName。
三、作用域鏈(Scope Chain)
在說作用域鏈的時候,要分為兩個“時間點”:函數創建時以及函數執行時。
這里借用夢想天空做的兩個圖:
函數創建時:
function add(num1,num2) { var sum = num1 + num2; return sum; }函數在創建時,會將它定義時刻的scope chain鏈接到這個函數對象的[[scope]]屬性,使其包含創建函數的那個時刻下,作用域中對象的集合,也就是函數的作用域鏈,這個作用域鏈直接決定哪些數據被函數訪問。
函數執行時:
var total = add(5, 10)函數執行時,創建一個活動對象,活動對象在一開始的時候,只包含arguments對象。
當遇到變量聲明時:
var a = 10;會將這個變量復制到活動對象中。
當遇到變量訪問時,會沿著作用域鏈做標識符解析(后續會提到),直至找到這個變量。
活動對象包含了函數的所有局部變量、命名參數、參數集合以及this,這些值按照它們出現在函數中的順序被復制到活動對象中。然后此對象會被推入作用域鏈的前端,當運行期上下文被銷毀,活動對象也隨之銷毀。
標識符解析
作用域鏈的用途,是為了保證對執行環境有權訪問的對象的有序訪問。標識符解析沿著作用域鏈一級一級地搜索標識符。搜索過程始終從作用域鏈的最前端開始(活動對象),逐級向后訪問(直到全局對象),直至找到標識符為止,如果找不到,則會報錯。
其他書單
JavaScript框架設計-司徒正妹
大放異彩的偽元素——可以做什么?
當我們談論顏色時,我們在談論什么 - 基礎知識篇
參考文獻
JavaScript 開發進階:理解 JavaScript 作用域和作用域鏈
Javascript作用域原理
轉載于:https://www.cnblogs.com/smoothLily/p/4468353.html
總結
以上是生活随笔為你收集整理的[JavaScript] JavaScript作用域深度解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Launchy – 快速调出你的程序
- 下一篇: 外存