跟我念 bi 闭 bao包 ,闭包的闭,闭包的包。。
闭包的简介
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
闭包的概念出现于60年代,在一些语言中,在函数中(嵌套)可以定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。运行时,一旦外部的函数被执行,一个闭包就形成了,闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用。其中所引用的变量称作上值(upvalue)。
闭包一词经常和匿名函数混淆。这可能是因为两者经常同时使用,但是它们是不同的概念。
(引用 维基百科)
写一个闭包
function start() {
var name = "xiaoming"; // name 是局部变量
function displayName() { //1. displayName() 是内部函数,满足了 函数内嵌
alert(name); // 2.使用了父函数中声明的变量,引用了外部变量
}
displayName(); // 3.执行(注意这一步调用后闭包才会生成,形成实例)
}
start();
- 注意 1 , 2, 3 必须同时满足才能形成闭包
运行代码可以发现 displayName()
内的 alert()
语句成功的显示了在其父函数中声明的 name
变量的值。
拓展应用
定时器
function add(x, y) {
setTimeout(function () {
console.log(x + y)
}, y * 1000)
}
for (var i = 0; i < 10; i++) {
add(1, i)
}
- 运行虽然闭包会生成一个实例,但值得注意的是,传入的值不能是对象,因为对象引用的内存地址没有改变。基本类型不受影响。
外部调用
var nADD
function f1() {
var n = 1
nADD = function() { // 外部变量,赋值,不满足内嵌
n += 1 // 引用了外部变量的值
console.log(nADD, n)
}
return function f2() {
console.log(n)
}
}
var result = f1()
result()
nADD()
result()
运行闭包常用的方式,反而是外部调用。这样可以让外部直接访问内部变量,很方便
实现单例
var person = (function() {
var instance = null
var name = 'Peter'
var age = 20
function initial() {
return {
getName: function() {
return name
},
getAge: function() {
return age
}
}
}
return {
getInstance: function() {
if(!instance) {
instance = initial()
}
return instance
}
}
})()
// console.log(person)
// console.log(person.initial().getAge()) 错误
console.log(person.getInstance().getAge())
使用闭包的注意点
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
网友评论