Closures are Functions with Preserved data
當一個對象不在被引用時,就會被 GC 回收,
反之則 該對象一直保存在 記憶體當中。
function A() {
var count = 0
function B() {
count++
console.log(count)
}
return B
}
var C = A()
C() // 1
C() // 2
C() // 3
// outer func
var addTo = function (passed) {
// inner func
var add = function (inner) { return passed + inner }
return add
}
console.dir(addTo(3))
// 實際應用 (我們可以保存變數於函式內)
var addThree = addTo(3)
var addFive = addTo(5)
// 查看 [[Scopes]] Closure 可見 passed 保存了不同的值
console.dir(addFive)
console.log(addThree(3)) // 6
console.log(addFive(3)) // 8
// 上面的 addFive(3) 等同於
// IIFE 執行 內部 add Func 並回傳其值
// (因addTo回傳function,而addTo()會執行該Func)
(function add(inner) {
return 5 + inner
})(3)
var makeCounter = function() {
var privateCounter = 0
function changeBy(val) { privateCounter += val }
return {
increment: function() { changeBy(1) },
decrement: function() { changeBy(-1) },
value: function() { return privateCounter }
}
}
// 建立兩個計時器,使用不同的環境,互不影響
var counter1 = makeCounter()
var counter2 = makeCounter()
console.log(counter1.value()) // 0
counter1.increment()
counter1.increment()
console.log(counter1.value()) // 2
counter1.decrement()
console.log(counter1.value()) // 1
console.log(counter2.value()) // 0
function Book(title) {
console.log('This will Run')
this.title = title
this.private = 'Cant Get!'
this.public = 'Can Get!'
this.getSummary = function () { return `${this.title}` }
return {
title,
public: this.public,
getSummary: this.getSummary,
}
}
const b1 = new Book('Book One')
console.log(b1.public) // Can Get !
console.log(b1.private) // undefined
const counter = function() {
let count = 0
function addOne() { count++ }
function setFive() { count = 5 }
return {
addOne,
setFive,
count,
value() { return count }
}
}
const countA = counter()
const countB = counter()
countA.addOne() // 執行addOne 無return值
countA.addOne() // 執行addOne 無return值
// 取得 countA物件之下的count (不會被更新!)
console.log(countA.count) // 0
// 取得 countA物件/valueFunc/[[Scope]]/Closure {count:1}
console.log(countA.value()) // 2 (取得count)
countA.setFive()
console.log(countA.value()) // 5 (取得count)
console.log(countB.value()) // 0 (不受影響)
VO 環境的變數物件,裏面會存該函式宣告的值 Ex:var a = 1;
函式執行環境中 定義了一個 scope chain 屬性,它負責記錄包含自己的 VO + 所有上層執行環境的 VO 的集合。
因此可藉由該屬性,內部函式可以存取外部函式的變數,反之則否。
代表函式內部定義的程式碼是根據定義時決定其值而不是動態決定。
Youtube講解影片
MDN
參透Javascript閉包與Scope Chain