Day02 : 在 React 中可能會碰到的 JavaScript 觀念


我在學 React 的過程中,常常懷疑人生,應該是因為沒把 JS 學好的關係。

在這邊會提到許多在 React 中常見的 JavaScript 觀念,也會有在學習過程才碰到的 ES6 用法,這些語法可以讓在撰寫 React 更為方便。

1. var, let, const

這應該是網路上已經有超級多的分享,如果你跟我一樣是靠線上課程的學習者,大多課程並不會全程使用 letconst,通常都是先使用 var 用到最後,而在章節最後提到 ES6 時才會講解,一開始在宣告時也是不知道到底用哪個比較好,這邊分享一下我的理解。
在 JavaScript 中,宣告 var 的位置會因為作用域(scope)而有不同結果,而作用域也分成兩種:

  1. Function Scope 函式作用域:函式範圍內
  2. Global Scope 全域作用域:全域範圍內
var score = 80

function plus(){
    var score = 90
    console.log(score) //90
}
plus()
console.log(score) //80

用這個例子就可以來解釋作用域(scope)了,在 JavaScript 的運作中,會從外找到內,而在 Function 內的 console.log 則找到 Function 內的 score 因此他會變成90。

由這個例子我們可以得知宣告 var 時的作用範圍是依據 Function Scope 及 Global Scope。

那 let 跟 const 呢?

letconstvar 不同,letconst 的作用範圍是看 block,也就是 {},function 的{}就是 block,只有{}也是 block。

{
    let score = 80
}
console.log(score)//score is not defined

{
    const name = 'Ronn'
}
console.log(name)//name is not defined

如果你把這段放進 VSCode 編輯器,你可以發現它會讓變數名稱會變灰色的,如果用 var 就會正常。

從此可得知,let/const 的作用範圍在大括號裡面,透過這樣的性質我們可以確保該變數不會受到 block 以外的影響。

那 let 跟 const 的差別?

const 全名為 constant,也就是常數,他通常被宣告在不會變動的值,如果值被變動,就會出現錯誤。

const PI = 3.14

像圓周率這種固定的常數,就很適合宣告 const。

const weekend = 2
weekend = 4 //TypeError: Assignment to constant variable.

不過若宣告 const 成物件或陣列,則可以修改物件底下的值,之所以沒有問題的原因是因 JavaScript 在儲存陣列及物件時,是放在對應的記憶體位置,而修改記憶體內的值並不是修改到變數本身。

var num = [2,3,4]
num.push(5)
console.log(num)//[ 2, 3, 4, 5 ]

但你若是把物件/陣列再定義成新的陣列/物件,就會不行,因為你賦予它新的記憶體位置

const num = [2,3,4]
num = [1,8]
console.log(num) //TypeError: Assignment to constant variable.

懶人總結一下:

  1. var 是透過作用域(scope)決定。
  2. let/const 是透過區塊(block)決定。
  3. const 通常用來宣告不會修改值的變數。

箭頭函式(Arrow Function)

我到了 React 學習階段才開始頻繁使用箭頭函式,因為實在是太方便了,除了寫法簡潔不冗長,在 this 的使用上更好用。


//傳統函式
Function test(a) {
    console.log(a)
}

//箭頭函式
const test = (a) => {
    console.log(a)
}

傳入參數的括號若只有一個參數可以省略,但多個就需要保留。

this 的差異?

傳統函式:依據它怎麼被呼叫而定 this
箭頭函式:依據它定義時外層而定 this

  • 請記住,箭頭函式沒有自己的 this
const a = {
    name: 'Object',
    arrowCall: function() {
        setTimeout(() => {
            console.log(this.name) //Object
        }, 10)

    } 
}
a.arrowCall()

上圖的例子可以知道一件事情,箭頭函式沒有自己的 this,他會去找外層 functionthis,也就是 Object。

我們在針對上面的例子,將 arrowCall 也改成箭頭函式。

const name = 'Global'
const a = {
    name: 'Object',
    arrowCall: () => {
        setTimeout(() => {
            console.log(this.name) //Global
        }, 10)

    } 
}
a.arrowCall()

由於 setTimeout 的外層也是箭頭函式,它也沒有自己的 this,因此會再往外層找,就到了全域環境的 Global。

由於箭頭函式還有一些特色,有興趣可以參考卡斯伯的講解。

解構賦值(Destructuring)

這個更慘,我到 React 才看過這樣的用法,這在 React 也是超重要,基本上善用這技巧可以精簡化很多程式碼

let state = {
    count: 1,
    isShow: true
}

let {count, isShow} = state
console.log(count, isShow)// 1 true

請注意賦值的名稱一定要一樣,不然無法使用(為此 Debug 許久)

另外如果是在陣列賦值,可以這樣做:

let [x, , z] = [10, 11, 12];
console.log(x, z); // 10, 12

擴展運算子(Spread Operator)

這也是我在看別人 React 的 code 第一次看到,主要是簡化了陣列展開的方式。

let split = [1, 2, 3]
console.log(...split) //1 2 3

在變數前面加三個點,應用方式很多,更多內容可以參考這篇

總結

以上就是我在 React 學習過程中沒打好的基礎,希望在看文章的你可以在碰 React 前能先把這些了解,讓在學習的過程不會跟我一樣卡。

#React





React 七天寫作松
透過短短的七天,稍微把我對 React 的見解整理成七天份的文章,希望能對正在初學 React 的你有所幫助!

留言討論