閉包
- 作用域應用的特殊場景有兩種表現
- 函數作為參數被傳遞
- 函數作為返回值被返回
//函數作為返回值
function create() {
const a = 100
return function () {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
// 函數作為參數被傳遞
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn) // 100
// 所有的自由變量的查找,是在函數定義的地方,向上級作用域查找
// 不是在執行的地方!!!
this
- 作為普通函數
- 使用call,apply,bind
- 作為對象方法被調用
- 在class方法中調用
- 箭頭函數(返回上級作用域的this)
this的取值是在函數執行的時候確定的,不是在定義的時候確定的
手寫bind函數
// 模擬 bind
Function.prototype.bind1 = function () {
// 將參數拆解為數組
const args = Array.prototype.slice.call(arguments)
// 獲取 this(數組第一項)
const t = args.shift()
// fn1.bind(...) 中的 fn1
const self = this
// 返回一個函數
return function () {
return self.apply(t, args)
}
}
function fn1(a, b, c) {
console.log('this', this)
console.log(a, b, c)
return 'this is fn1'
}
const fn2 = fn1.bind1({x: 100}, 10, 20, 30)
const res = fn2()
console.log(res)
實際開發中閉包的應用
// 閉包隱藏數據,只提供 API
function createCache() {
const data = {} // 閉包中的數據,被隱藏,不被外界訪問
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log( c.get('a') )
創建十個a標籤,為每個綁定事件
let a
for (let i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}