iT邦幫忙

0

#03 學習筆記Javascript Scope Chain(範圍鏈)

Eazy 2023-06-04 23:25:351126 瀏覽
  • 分享至 

  • xImage
  •  

上一篇文章有提到關於Scope chain的部分,今天整理完就來介紹一下吧/images/emoticon/emoticon07.gif

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 = 1

function 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):往外找


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

1 則留言

1
alien663
iT邦研究生 3 級 ‧ 2023-06-06 14:00:42

Javascript是一款直譯式語言,但有一點很特殊,他會先把所有變數先做好宣告,才去執行其他程式碼,也就是如果用var宣告變數時,你可以在賦予值之前就先呼叫他。這樣的狀況容易發生變數汙染,在多人合作專案裡會出大事的,因此ES6語法新增了let與const,在賦予值之前會先將變數上鎖,讓你無法呼叫,以及加入Scope的概念,解決變數汙染易發的問題。
如以下範例 :

console.log(t1)
var t1 = "KK"
console.log(t2)
let t2 = "KK"

Scope 內外關係 :

let i = 10
for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        for(let k=0;k<3;k++){
            let j = 10
            console.log({i, j, k})
        }
    }
}
看更多先前的回應...收起先前的回應...
Eazy iT邦新手 4 級 ‧ 2023-06-07 22:56:15 檢舉

開始好奇大大的前端框架學習路程了XD

alien663 iT邦研究生 3 級 ‧ 2023-06-08 17:42:40 檢舉

這其實跟前端框架的學習路程沒有太大關係,我是在大學有幸遇到好教授,開授Programing Language這堂課,讓我學會從底層的運作方式去認識一個語言,了解一個語言的底層細節,變成了我學習的一大重點。不過我覺得這樣的方式並不適合非資工系的人,因為會需要補充太多的基本概念才有辦法這樣學習,如果只是想要轉換跑道,專注在增強實作能力比較實際一點,想要提升技術等未來薪水和時間充裕了再說。

扯遠了。
我實際接觸前端,是從基礎的HTML、CSS、Javascript開始,然後從專案實作中學習JQuery、EJS,也碰過.netframework 2.0的Webform,直到別人的帶領下開始使用React,作為我的主力前端框架至今。

去年也曾用專案實作的方式自學Angular和Blazor(個人偏見討厭Blazor,所以沒有做到一定程度就放棄了),Vue的部分僅僅用過幾個基本語法,會渲染前端而已。

雖然講了這麼多,但其實我是一個重心放在後端和資料庫的全端工程師,然後再囊括一點機房管理和伺服器架設。

Eazy iT邦新手 4 級 ‧ 2023-06-09 20:48:33 檢舉

謝謝大大詳盡的解說,我比較好奇的部分是要學習前端框架是否在原生JS語法非常熟悉以後在去做學習呢?
因為目前遇到的問題是到底要埋著頭學框架(而且有一派說法是說vue算是對新手較為友善)
還是應該把基礎JS學習到可以隨心所欲用手刻出來?

alien663 iT邦研究生 3 級 ‧ 2023-06-12 08:33:16 檢舉

看你的狀況而定,如果你現在有很多空閒時間可以研究,那就會建議從JS基礎開始學習。
若是希望趕快可以快速轉型使用,那就會事先學習框架優先,未來有空才來補JS。

我要留言

立即登入留言