範圍鍊(Scope Chain)
Def:
當函式本身使用的變數不存在 就會向外層尋找
(這裡的外層不一定是全域!!)
我們在前面有提到
當 函式fn1 沒有 num 變數時
會向外層尋找
而尋找過程與執行環境毫無關係 (請牢記!!)
是依據函式文法本身來決定範圍鍊
所以這裡的 fn1 與 fn2 的範圍鍊
皆指向 全域
var num = 1;
function fn1(){
//請看這裡
console.log(num);
}
function fn2(){
var num = 10;
fn1();
}
fn2();
提升(Hoisting)
重要!!
在 JS基礎篇 我們有提到
//這裡其實是兩個步驟
var name = '皮傑先生';
//宣告變數
var name;
//賦予值道變數上
name = '皮傑先生';
//這兩個結果會是一樣的
那到底是為什麼呢??
這裡我們要先來提一下 我們上一篇提到的 執行環境
在建立一個執行環境的時候
其實是有兩個階段
我們剛剛都是著重在 執行
那創造階段到底是做什事情??
創造階段
先將變數配置一個 記憶體空間
(所以用console來看會是undefined)
執行
賦予值
在創造環境把記憶體空間準備好
就稱為 提升(Hoisting)
比較不同的是
若是 函式陳述式(這裡是函式陳述式 並非函式表達式)
在創造階段就會優先載入(請牢記!!)
簡單來說
創造階段,函式已經可以執行
而變數要等到執行階段才會賦予值
例:
var a = '1';
function fn(){
//.....
}
創造階段
執行階段
例 1
var name; //創造階段
name = '皮傑先生'; // 執行
例 2
console.log(name); // undefined
var name = '皮傑先生';
例 3
function fn(){
console.log('皮傑先生') //皮傑先生
}
fn();
例 4
fn();
function fn(){
console.log('皮傑先生') //皮傑先生
}
例 5( 例3 , 例4拆解 )
//創造階段
function fn(){
console.log('皮傑先生')
}
//執行
fn();
會發現 例3 , 例4 皆會執行
是因為創造階段 函式就已經載入
而不會像 例2 呈現 undefined
因為變數是在執行階段 才賦予值
例 6 (函式表達式)
fn();
var fn = function(){
console.log('皮傑先生'); //undefined
}
例 7 ( 例6拆解 )
//創造階段
var fn; //配置記憶體 但尚未賦予值
//執行
//若使用函式表達式 要等到函式賦予到變數上 才能運行函式
fn();
fn = function(){
console.log('皮傑先生'); //undefined
}
這裡要額外提一個重要觀念
在 創造階段的時候 函式優先(請牢記!!)
這裡舉個例子 方便釐清
例 8
var fn = function(){
console.log('皮傑先生 2');
}
function fn(){
console.log('皮傑先生 1');
}
fn(); //皮傑先生 2
例 9
// 兩個函式位置互換
var fn = function(){
console.log('皮傑先生 2');
}
function fn(){
console.log('皮傑先生 1');
}
fn(); //皮傑先生 2
會發現 例8 , 例9
皆為 皮傑先生 2
為什麼!!!!
因為上面有提到
在創造階段的時候函式優先
例 10 ( 例8 , 例9拆解 )
//創造階段
//函式優先
function fn(){
console.log('皮傑先生 1');
}
var fn;
//執行
fn = function(){
console.log('皮傑先生 2');
}
fn();
例 11
fn();
function fn(){
console.log(man); //undefined
}
var man = '皮傑先生';
//拆解
//創造階段
function fn(){
console.log(man);
}
var man;
//執行
fn(); // 這裡執行 fn 時 , man尚未賦予值 所以為undefined
man = '皮傑先生';
例12
function fn(){
console.log('皮傑先生'); //小雞公主
}
fn();
function fn(){
console.log('小雞公主'); //小雞公主
}
fn();
//拆解
//創造階段
function fn(){
console.log('皮傑先生'); //小雞公主
}
function fn(){
console.log('小雞公主'); //小雞公主
}
//執行
fn();
fn();
//所以函式名稱相同的話 後面的會覆蓋前面的
那今天的介紹就到這裡啦~~
內容很多 也很重要
務必多看幾次
明天我們將介紹
執行緒與同步非同步
若有任何問題 或 內容有誤
請別吝嗇的跟我說唷~~