上一篇文章有提到关于Scope chain的部分,今天整理完就来介绍一下吧
Scope(範围、範畴)
这边先把这两个名词Scope跟Chain分开,在JS的世界里Scope有点类似变数可以被看到或作用的範围。
怎么听起来有点像咒术战里的领域展开
有分为全域变数跟区域变数
全域变数
变数若未在Function或是Block中宣告的变数,这样变数就是一个全域物件。
let str1 = '我是帅哥'Fuction callMehandsome (){ console.log(str1);}callMehandsome(); //印出我是帅哥
可以在任何一个地方使用这个变数,因为它是一个全域变数。所以记得要使用变数之前一定要记得宣告,不然就会成为全域物件会造成全域污染
区域变数
变数若在Function或是Block中宣告的变数,这样变数就会是一个区域变数。
区域变数又可以切分成两个作用区域Funticon Scope 跟 Block Scope。
function Scope
JS中var的範围设定就是function Scope,所以今天用var宣告变数:
function addNumber(){ var a = 2; var b = 3; console.log(a + b);}addNumber();
简单一点来说,a跟b这两个变数在Function中被宣告后会成为区域变数,离开这个Function后可以再重新宣告。
因为a跟b会被关在Function中,离开这个Function后就不会存在。
那假设如果我今天没有在function内宣告呢? 那就会往外层去找是否有宣告变数!
var a = 1function printA (){ console.log(a)}printA();
你一定也想问如果外层也没有呢? 那就会往window去找!
所以才会一直强调为什么变数要使用前一定要宣告
Block Scope
那在ES6后出现let跟const之后的範围设定又有点不太一样,是Block Scope。
funticon跟block两者之间的差异在于block是用{ }
大括弧(curly brace)来定义区域,而funtiocn是用funtcion(){ }
。
{ const age = 18 console.log(age);}
简单来说在一个{ }
用let或是const宣告变数,离开这个大括弧以后这个变数也就不存在了。
Scope Chain
这边就不啰唆,直接上程式码伺候
var age = 18; function a (){ var age = 38; b();}function b (){ console.log(age);}b(); //这边出来的结果是18
为什么会是这个结果呢?
明明函式a有重新宣告age的值跟呼叫函式b?又或是函式b也没有宣告age这个变数啊,应该也是 undefinded
。
其实js已经替function b 建立了他的函式执行环境,而在建立执行环境的时候,也替他建立了 this
和 外部环境参考(Reference to Outer Environment)。
对 function b 来说,他自己没有 age 这个变数,所以他往外部参考环境找,而他的外部环境是全域,不是 function a。所以 function b 取得的是全域变数 age = 18。
而 function b 这个往外找的这个行为,就是所谓的範围链 (Scope Chain)。
因为程式总不能动不动就喷错吧
参考文章
[JavaScript] Javascript 的作用域 (Scope) 与範围链 (Scope Chain):往外找