iT邦幫忙

1

JS 範圍鍊 與 提升 DAY49

範圍鍊(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(){
    //.....
}

創造階段
https://ithelp.ithome.com.tw/upload/images/20201014/20123039KAfxFu4l1w.jpg

執行階段
https://ithelp.ithome.com.tw/upload/images/20201014/201230393q0UKYOcrs.jpg

例 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();

//所以函式名稱相同的話 後面的會覆蓋前面的

那今天的介紹就到這裡啦~~
內容很多 也很重要
務必多看幾次/images/emoticon/emoticon07.gif
明天我們將介紹
執行緒與同步非同步
若有任何問題 或 內容有誤
請別吝嗇的跟我說唷~~


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言