在任何JS核心引擎中,都有一張全局表來存儲全局變量閉包
const _ = require('../util/understore')
// 動態做用域,任何JS核心引擎中,有個全局查找表
const globals = {}
const makeBind = resolver => (name, val) => {
const stack = globals[name] || []
globals[name] = resolver(stack, val)
return globals
}
const stackBinder = makeBind((stack, val) => {
stack.push(val)
return stack
})
const stackUnBinder = makeBind((stack) => {
stack.pop()
return stack
})
const dynmicLookup = (name) => {
const slot = globals[name] || []
return _.last(slot)
}
stackBinder('a', 1)
stackBinder('a', 2)
stackBinder('b', 100)
console.log(dynmicLookup('a'))
stackUnBinder('a')
console.log(dynmicLookup('a'))
const f = () => {
return dynmicLookup('a')
}
const g = () => {
stackBinder('a', 'g')
return f()
}
console.log(f())
// 動態做用域的缺點,任何綁定值,在肯定調用函數以前,都是不可知的。
console.log(g())複製代碼
咱們沒法精確控制函數中的this是什麼,由於函數的this由調用者決定。
因此,咱們須要在調用函數前進行綁定。函數
const bindAll = (obj, ...funs) => {
return funs.map(fun => obj[fun] = obj[fun].bind(obj))
}
const target = {
name: 'name',
a: function () {
return this.name
},
b: function () {
return this.a()
},
}
console.log(target.b())
// 如下方式會報錯
// console.log(target.b.call('lhj'))
// 使用bindAll解決這個問題,預綁定
bindAll(target, 'a', 'b')
console.log(target.b.call('lhj'))複製代碼
閉包的用途很是普遍,任何函數內部能讀取外部變量(包括參數,全局變量,私有變量),這就造成了一個閉包。ui
// 求平均數
const average = array => array.reduce((prev, next) => prev + next) / array.length
// 求指定數字與經過函數生成另一個數字
const averageDynmic = fun => n => average([n].concat(fun(n)))
console.log(averageDynmic(n => ([n * n]))(10))
// 求反義函數
const complement = fun => (...args) => !fun(...args)
const isOdd = n => n % 2 === 0
const isEven = complement(isOdd)
console.log(isOdd(1), isOdd(2))
console.log(isEven(1), isEven(2))
// 封裝數據
const Team = () => {
let num = 1
const people = {
lhj: {
age: 30,
},
}
return {
add: n => num += n,
del: n => num -= n,
update: (name, value) => people[name] = value,
}
}
const t1 = Team()
console.log(t1.add(3))
console.log(t1.del(2))
console.log(t1.update('lhj', {
age: 31,
}))複製代碼