主要學習閉包使用,因為自己不太熟悉閉包使用方式所以趁這次鐵人賽試著拿閉包來實作,在進到實作之前會簡單介紹閉包
要先知道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的參照
每個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
科里化:接受多個參數的函數變換成接受一個單一參數
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