谈谈闭包的应用场景
导语:在之前简单介绍了一下闭包以及闭包的作用。这一期聊一聊闭包的应用场景。
一.单例的实现
所谓单例就是在全局中,这个类提供了一种访问其唯一的对象的方式。注意关键词就是这个对象是唯一的,也就是说调用该单例创建方法都会返回同一个对象。
function Person() {
this.name = 'ouda'
}
Person.sharedInstance = (function () {
var instance;
return function () {
if (!instance) {
instance = new Person()
}
return instance;
}
})()
const p1 = Person.sharedInstance()
const p2 = Person.sharedInstance()
console.log(p1 === p2)
p1 和 p2 都是通过 sharedInstance() 进行创建的,他们访问到的都是同一个内部变量 instance,形成了一个闭包,所以 p1 和 p2指向的都是同一个对象。那么只要通过这个方法创建出来的对象就是同一个,且唯一,这就是闭包在创建单例的应用场景。
二.属性的私有化
当我们对一个变量想要进行保护,不想给外部直接访问时,我们可以利用闭包将变量私有化。
假设这样一个应用场景,在一个游戏中,你有3条命,当你达到条件时,生命+1,触发另一种场景时生命 -1,为了保护生命值这个变量只能够按照规则 +1 或者 -1,不允许被别的函数修改或者在其他作用域访问,我们可以这样做:
function Role() {
var life = 3
this.addLife = function () {
life++
return life
}
this.minLife = function () {
life--
return life
}
this.getLife = function () {
return life
}
}
const role = new Role()
console.log(role.addLife()) // 4
console.log(role.addLife()) // 5
console.log(role.minLife()) // 4
role.life = role.life + 100
console.log(role.getLife()) // 4
可以发现 Role 下的 life变量我们只能通过 addLife 和 minLife 这两个方法进行改变,并且改变的规则在函数内部自己规定。直接通过 role.life是访问不到该变量的,更不用说试图去更改他的值了。
三.函数的科里化
什么是科里化?
柯里化(
currying),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
如果要实现一个数字的累加器(1+2+3+4....)
初级写法:
function sum(a, b) {
return a + b
}
let res = sum(1, 2)
res = sum(res, 3)
res = sum(res, 4)
console.log(res) // 10
需要加多少次就写多少个sum函数。
中级写法:
function sum() {
const numbers = Array.from(arguments)
return numbers.reduce((a, b) => { return a + b })
}
console.log(sum(1, 2, 3, 4, 5, 6)) //21
通过函数 arguments 巧妙地将参数个数不作限制。
科里化高级写法:
function sum() {
var numberList = Array.from(arguments)
var _sum = function () {
numberList = numberList.concat(Array.from(arguments))
return _sum
}
_sum.valueOf = function () {
return numberList.reduce((a, b) => { return a + b })
}
_sum.toString = function () {
return numberList.reduce((a, b) => { return a + b })
}
return _sum
}
const res = +sum(1, 2, 3)(4)(5, 6)
console.log(res)
调用更加随心所欲,可以不限制参数,并且可以链式调用,函数的科里化,就是用到了闭包实现的。 numberList就是闭包中的私有变量。