iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Modern Web

初學者跪著學JavaScript系列 第 23

初學者跪著學JavaScript Day23 : 閉包簡單用

  • 分享至 

  • xImage
  •  

主要學習閉包使用,因為自己不太熟悉閉包使用方式所以趁這次鐵人賽試著拿閉包來實作,在進到實作之前會簡單介紹閉包

要先知道scope作用域:

w3school:Scope determines the accessibility (visibility) of variables.

範圍內是否有存在的變數

閉包

mdn:

中文:閉包(Closure)是函式以及該函式被宣告時所在的作用域環境(lexical environment)的組合
英文:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

為什麼這麼說?
在還沒執行函式會先定義lexical environment(scope) ,在執行函式時會出現stack 裡的execution context 內,到時會到scope去找要使用的變數,如果自己scope沒有找到該變數的話就會往外層scope找尋,

閉包就是函式執行完後在stack裡的execution context 消失,當函式內還有內部函式,內部函式會保留對父層scope的參照

scope找變數

每個function會有自己的scope

function school() {
    let teacher = 'maggie';
    function student() {
        console.log(teacher);
    }
    student();
}
school();//maggie

理解如何找變數:
內層function可以找到外層function 變數teacher,原因是自己的scope找不到變數,會往外層找變數teacher

舉個例子:
假如我要

5+10
5+20
5+30

 function add5(x) {
     return x + 5;
 }
 console.log(add5(10));//15
 console.log(add5(20));//25
 console.log(add5(30));//35

每次執行函式時回傳值都會加5
那要如何使用閉包達到這個效果呢?

閉包方式:

最基本使用方式:外部function return內部function

巢狀函式

函式內的返回值是function
在add51變數保留對父層scope的參照
如下:

function addY(x) {
    return (y) => x + y;
}
let add5 = addY(5);
console.log(add5(10));//15
console.log(add5(20));//25
console.log(add5(30));//35

當返回值是一個物件時

如下:

function addx(x) {
    return {
        go: (y) => x + y,
    };
}
let add5 = addx(5);
console.log(add5.go(10));//15
console.log(add5.go(20));//25
console.log(add5.go(30));//35

進階使用:

return 裡面放一個物件,該物件內放各種方法,這方法叫閉包私有化

如下:
創建沒有除法的計算機

function calculator() {
    let set = 0;
    return {
        add: (y) => (set += y),
        sub: (y) => (set -= y),
        mul: (y) => (set *= y),
    };
}

let myCalculator = calculator();

console.log(myCalculator.add(1));//1
console.log(myCalculator.add(2));//3
console.log(myCalculator.add(3));//6
console.log(myCalculator.add(4));//10
console.log(myCalculator.mul(4));//40

return一個物件裡面放對set變數計算的methods

科里化(Currying)

科里化:接受多個參數的函數變換成接受一個單一參數

function add(a, b, c) {
    return a + b + c;
}

console.log(add(10, 20, 30));//60

let add = (number1) => (number2) => (number3) => {
    return number1 + number2 + number3;
};
let x = add(10);
let y = x(20);
let z = y(30);

console.log(z);//60

注意:一開始學習比較容易搞混的地方

function counter(){
  var count = 100 //在外部函式中宣告變數和內部函式;
  return function(){//在外部函式內返回內部函式;
    return ++count  //使用內部函式訪問或者修改變數值
  }
}

//一個括號不會執行到內嵌的函式
console.log(counter()) // 印出funciton

//使用兩個括號會重新整個執行一次
console.log(counter()()) // 印出100
console.log(counter()()) //印出100

//閉包
 const go = counter()
 console.log(go()) //印出 101
 console.log(go()) //印出 102
 console.log(go()) //印出 103
 console.log(go()) //印出 104


https://javascript.plainenglish.io/closures-in-javascript-37182198dc20
mdn


上一篇
初學者跪著學JavaScript Day22 : 我要原型繼承,constructor又不走丟
下一篇
初學者跪著學JavaScript Day24 : 原型不會,但你還有class
系列文
初學者跪著學JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
南國安迪
iT邦新手 3 級 ‧ 2021-10-08 21:04:56

哇~~~都不知道可以這樣用耶
/images/emoticon/emoticon58.gif

我要留言

立即登入留言