作用域 Scope、作用域链 Scope Chain

在初学阶段,还蛮常碰到明明定义好的变数却回报 error,可能是因为对 Scope 的观念没有理解。

什麽是 Scope ?

我习惯称 Scope 为作用域,有人称为范畴,是一个用来查找、访问变数及函式的规则。
在 ES6 的 let、const 出现之前,我们只有函式作用域 ( var ),但 ES6 後多了区块作用域,主要是定义了 let、const 作用范围 。

简单来说,作用域表示变数或者函式有作用的地方。

function sayHi(){
	var guy = 'Lisa'
	function greet(){...}
  console.log(guy)
}

console.log(guy)
greet()

上面程序码,我们在全域宣告了一个函式 sayHi ,函式里面宣告变数 guy 以及函式 greet,但当我们想从全域取用 guy 跟 greet 就会报错,因为这两者的作用域在 sayHi 里面。

但为什麽下面的例子,我们可以访问函式以外的变数?

var idol = 'Rose'

function sing(){
  console.log(idol)
}

sing()

idol 宣告在全域环境,却能在 sing 函式里呼叫,这是靠作用域链 Scope Chain 查找的结果。

前几篇讲执行环境 Execution context 的时候,我们提到 JS 遇到函式调用时会创建一个属於该函式的执行环境,每个函式内部有自己的 [[scope]],调用函式时的执行环境会把 [[scope]] 跟 Scope Chain 连结。

当全域执行环境建立时,创造阶段初始化了全域的 variable object 以及 scope chain。

globalExecutionContext:{
	VO:{
		idol:undefined,
		sing:function
	},
	ScopeChain:{
		globalExecutionContext.VO
	}
}

// 并且宣告 sing 函式时,sing 的作用域会参考由全域给的 scopechain 的内容
sing.[[scope]] = globalExecutionContext.ScopeChain

接着 sing() 被调用,因着 sing 的 scope 可以透过 scoope chain 取得外部全域的变数

此外,若无使用宣告定义变数的话,则 JS 会视为全域变数 ( 这是不好的习惯哦~ )

var idol = 'Rose'

function sing(){
  fruit = 'grape'
}

console.log(fruit)

<<:  Day 5 : 基本常识以及变数

>>:  18.移转 Aras PLM大小事-快速贴入ECR受影响物件

Day11 主动情蒐-建立练习环境 metasploitable3

因为我们之後练习需要透过 metasploitable 3 当作靶机,所以要先安装 metaspl...

[DAY9]制作容器(八)

9/25: 隔一天才发现因为前一天字数不够,草稿发文不成功所以断赛了QQ 还是把昨天测试的结果放上来...

Day12 再靠近一点点 就不闪躲

Cursor and Zoom-in 今天继续增加图表功能,其中两个很常需要的功能就是游标和区域放...

Day09:Emit Direct Message I(发送个人讯息到 server 端)

全文同步於个人 Docusaurus Blog 当建立私人频道後,下一步,便是将私人频道的讯息发往...

Day6 梯度提升树(Gradient Boosting Decision Tree)

梯度提升树是什麽? 讲人话就是将随机森林的概念更进一步应用,策略性地逐步建构多棵决策树模型,间接让重...