JS作用域精講

什麼是作用域?

  • 一句話概括:JS用來存儲變量的地方
  • 爲了給大家更官方更準確的解釋這裏我們引用《你不知道的JS(上)》裏面的解釋:
    幾乎所有編程語言最基本的功能之一,就是能夠存儲變量當中的值,並且能夠在之後對這個值進行訪問和修改,事實上,正是這種存儲和訪問變量值的能力將狀態帶給了程序。
    若沒有了狀態這個概念,程序雖然也能夠執行一些簡單的任務,但他會受到高度限制,做不到非常有趣。
    但是將變量引入程序會引起幾個很有意思的問題:這些變量存儲在哪裏,或者說“程序在執行時通過什麼找到它?”
    這些問題說明這需要一套設計良好的規則來存儲變量,並且之後可以方便的找到這些變量,這套規則即被稱爲作用域

編譯原理(作用域裏是怎麼有東西的?)

  1. 當我們定義一個變量並給他賦值時var a = 1;其實JS引擎分開了兩步來執行:1.var a聲明這個變量,並將它放到當前作用域中去 2.a = 1在作用域中找到變量a然後將其賦值1

  2. 函數亦是如此:當我們聲明一個函數時function fn(){}JS引擎同樣將其分開了兩步來執行:1.function fn()function相當於var,將fn加入到當前作用域中,並且值爲函數體

**注:**函數聲明分兩種:1.function fn(){}這種叫函數聲明,當將fn加入到作用域中時它的值就直接是函數體了不經過undefined 2.var fn = function (){}這種叫函數表達式,它的執行過程是先在作用域中添加fn變量此時的值爲初始值undefined,然後當執行到這一行時纔將函數體賦值給fn

具體變量是如何加進入作用域的請看我的預編譯文檔(記得點個小關注)

作用域是如何產生的?

  1. 當我們執行一個函數時會產生一個AO(函數作用域)
  2. 默認有一個GO(全局作用域)

作用域查找變量流程

在這裏插入圖片描述
根據上圖我們模擬以下程序:

var name = 'luopo';
var age = 18;
function fn(){
	var name = 'daniu';
	console.log(name, age);
}
fn()

函數fn外面的變量的作用域就是我們的全局作用域
函數裏面的變量的作用域就是我們的函數作用域
接下來我們看代碼:
在全局作用域中我們擁有兩個變量和值分別是:
name : ‘luopo’
age : 18
在函數fn的函數作用域中我們擁有一個變量和值分別是:
name : ‘daniu’
執行到console.log(name, age)時:
我們的JS引擎就會找到作用域哥們們,首先找自己這個函數的作用域哥們,

  • 問他:“我的函數作用域哥們你有看到name這個變量嗎?我想要它的值”

  • fn函數作用域哥們回答:“有噠,它的值是’daniu’來給你把JS引擎好兄弟”!

於是我們的JS引擎就拿到了name的值爲’daniu’

  • 接下來JS引擎又問:“我的函數作用域哥們你那看看有沒有age這個變量啊?我想要它的值”
  • fn函數作用域老哥:“對不起這東西我這裏沒有呢,很抱歉沒能幫到您,要不您去問問GO(全局作用域)爸爸吧!”
  • 於是JS引擎屁顛屁顛的就跑來問全局作用域了:“爸爸你這裏有沒有age這個變量呀,我想要它的值”
  • 全局作用域:“啊,爸發現啦,來兒子它的值爲18,給你拿去吧!”
    於是我們JS引擎就拿到了age的值爲18

所以程序的執行結果爲:'daniu'18

總結

函數作用域相當於全局作用域的兒子,兒子可以拿爸爸的東西,而爸爸不能拿兒子的東西,如果爸爸也都沒有的話在“非嚴格模式”下會讓爸爸添加一個這個新變量值爲初始值undefined,如果在“嚴格模式”下則會拋出異常ReferenceError: xx變量 is not defined,爸爸沒有的話則直接拋出這個異常。

寫的有很多不好的或者描述模糊的地方可以評論區多多指點,如果有寫的錯誤的地方也希望大家能在評論區指點出來,謝謝大家,希望能幫到大家更好的學習前端,一起加油!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章