上回与艾草玩游戏输了要接受处罚。
「都躲这麽远了,她应该找不到我了吧!」
艾草:「啊哈,原来你躲在这里呀!」
「你怎麽找到的?明明我跑超远了呀。」
艾草:「范围追踪魔法呀,如果 1 km 内找不到你,那魔法就 5 km 、 10 km 的帮我找,就不信找不出你。」
「啊啊,这魔法也太好用了吧,快点教我吧!我一直在找寻很重要的东西。」
艾草:「可以呀!是要找什麽?」
「我遗失这些年的女朋友 (இ﹏இ 。)」
在开始范围链 (Scope Chain)介绍之前,让我们先了解作用域是什麽东西吧!
JavaScript 会在程序运行之前语法解析阶段就决定作用域,称为语法作用域(Lexical scope)。
在先前的文章-变数宣告 let
、const
、var
有提到。
首先,我们先来谈谈 ES6 才新增的宣告方式
let
、const
, 与var
不同的地方在let
、const
作用域在区块,区块指的是{}
内,例如if
、for
回圈等,而var
的最小切分单位为function
。
作用域的划分大致可区分为:
var
宣告的函式作用域
let
、const
宣告的块状作用域
以程序码来举例:
let myName = "艾草";
function sayHello() {
var myName = "烙诗";
if (true) {
let myName = "筑茵";
console.log(`块状作用域打招呼${myName}`);
}
console.log(`函式作用域打招呼${myName}`);
}
console.log(`全域打招呼${myName}`);
sayHello();
印出结果:
实际上的作用域划分,会如下图所示:
简单来说 var
会被关在函式内, let
、const
会被关在 {}
大括号内,外层取用不到,而全域则是谁都可以取用。
外层作用域取不到内层作用域的值,但内层作用域如果找不到值,可以一直向外层作用域寻找,而这就是今天要介绍的范围链 (Scope Chain)的观念!
我们在撰写 JavaScript 时,有时会宣告全域变数,而在函式作用域内也能去取用该全域变数,而范围链便是指如果函式作用域内没有找到指定变数时会向不断向外寻找的过程,可以看到范例程序码函式内并没有宣告变数 a
、b
,却能取用到:
let a = 1;
let b = 1;
function add() {
console.log(a + b);//2
}
add();
如果在函式内呼叫另一个函式,那它会取到哪个变数呢?
另外定义了一个函式 test
,并於 test
内分别也宣告了变数 a
、 b
,并於 test
内呼叫 add
函式,会发现印出来的结果依然是 2 ,所以函式 add
依然取用到全域的变数 。
let a = 1;
let b = 1;
function add() {
console.log(a + b);//2
}
function test() {
let a = 3;
let b = 4;
add();
}
test();
因为函式的区域内没有该变数,所以它们会向全域寻找变数,为什麽在 test
函式内呼叫 add
函式并没有影响到 add
函式印出的结果呢?因为 JavaScipt 的作用域在一开始就决定了,并不受执行堆叠与何时调用的影响。
如果直接将 add
函式移进 test
函式内结果会一样吗?
let a = 1;
let b = 1;
function test() {
let a = 3;
let b = 4;
function add() {
console.log(a + b);//7
}
add();
}
test();
会发现印出来的结果与上方不同了,因为巢状函式内层的 add
函式在自己的作用域内找不到变数时,会往外层的 test
函式作用域寻找,而在 test
函式就能找到它需要的变数了,所以并不会继续全域环境查找!
var
宣告的变数为函式作用域
let
、const
宣告的变数为块状作用域
请问以下 console.log()
会印出什麽呢?
let a = 1;
let b = 1;
function test() {
let a = 3;
let b = 4;
function add() {
let a = 2;
let b = 2;
console.log(a + b);//?
}
add();
}
test();
欢迎丢进开发人员工具检视唷!
JavaScript 核心篇(六角学院)
https://codingbycolors.me/graphical_js_rules_scope/
<<: 【20】从头自己建一个 keras 内建模型 (以 MobileNetV2 为例)
灵异现象 - 怎麽大家都能改阿 灵异现象 故事主角:小新 小新的 IT 同事小王最近转部门跑去做 R...
根据相对论,如果一对挛生兄弟, 哥哥搭乘宇宙飞船,以接近光速,飞离地球,在宇宙间航行; 当回到地球的...
老歌了~ 宅男开YouTube来看,永远不缺手游广告... 最近有个广告台词,开局一定要选拳法,如...
本系列文之後也会置於个人网站 在这一小段路中介绍了Password Flow、Implicit F...
熟悉的起手式:「我方便问你一个 Node.js 核心的问题吗?」 这是一个在了解後,无论面试还是工...