前言
本文将从以下几个点来展开:
什么是闭包?怎么创建闭包?
闭包的应用
什么是闭包?
函数执行完,其内部函数还保持着对它的作用域的引用,这个引用就是闭包。
内部函数对包含它的函数作用域保持着引用意味着什么?
也就是函数执行完,内存被释放,但是其作用域还存在内部函数的执行上下文中,还能在内部函数中访问到函数作用域中的变量。
怎么创建闭包?
也就是如何让内部函数对包含它的函数的作用域始终保持引用呢?
没有创建闭包的例子:
function addValue() {
var value = 1
return function add () {
return value++
}
}
console.log( addValue()() ) //1
console.log( addValue()() ) //1
example1的栗子不能算闭包,因为内部函数并没有对包含它的函数作用域保持引用。每次调用addValue方法,value都是1。如果像example2一样将addValue返回的函数赋值给一个全局变量,那么在程序卸载之前,内部函数一直被全局变量引用着,所以addValue内存始终不会被释放。如下:
创建了闭包的例子:
function addValue() {
var value = 1
return function add () {
return value++
}
}
var b = addValue()
console.log( b() ) //1
console.log( b() ) //2
函数作用域是在执行时创建的,当函数执行完,内存就会被释放,函数内部变量不能在函数外部被访问。但是如果函数一直被引用着,那么函数内存就不会被释放,函数中的变量就不会被销毁,包含该函数作用域的函数就能访问到该函数中的变量。
对于一个函数而言,函数中的变量只能在被激活的时候才能访问到,也就是在函数内部才能访问到,当函数执行完内存就会被释放,也就是函数执行上下文就会被销毁,对应的执行上下文中的活动对象保存的变量也会被销毁。
基于js的垃圾(内存)回收机制,如果函数一直被引用着函数一直处于激活(被使用的)状态,其内存就一直不会被回收,其执行上下文一直存在,保存的变量对象也一直存在。
闭包的应用
1、创建私有模块
var module = (function() {
var person = {
name: "phillip",
age: 29,
location: "Utah"
};
function privateMethod(){
return "Hi, I'm " + person.name + ", age " + person.age + " from " + person.location;
}
// Anything that is being returned is made public and can be invoked from
// outside our lexical scope
return {
// Code here.
privateMethod: privateMethod
};
})();
module.privateMethod()
2、保留记录
var friends = ["Tom", "Dick", "Harry"];
var secondLevelFriends = ["Anne", "Harry", "Quinton"];
var allUsers = ["Tom", "Dick", "Harry", "Anne", "Quinton", "Katie", "Mary"];
function findPotentialFriends(existingFriends) {
return function (friend) {
return existingFriends.indexOf(friend) > -1 ? false : true
}
}
var isNotAFriend = findPotentialFriends( friends );
// isNotAFriend(allUsers[0]); // false
// isNotAFriend(secondLevelFriends[2]); // true
最后
检验闭包掌握情况:
function fo() {
var i = 0;
return function (n) {
return n+i++ //++ 先赋值再+1
}
}
var f = fo()
console.log(f(15)) //15
console.log(fo()(15)) //15
console.log(fo()(20)) //20
console.log(f(20)) //21
要了解闭包保存函数内部变量的原理,必须了解了函数执行上下文、变量对象、作用域链、函数作用域、垃圾回收内存释放的知识,可以参考下面的文章:
那么Js中到底是如何管理变量(什么时候会被回收内存)的呢?
http://note.youdao.com/notesh...
函数作用域(函数中如何访问变量呢)是怎么一回事呢?
http://note.youdao.com/notesh...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。