1. 概念
指有权访问另一个函数作用域中的变量函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
function a(propertyName){ return function(object1,object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; return value1-value2; }; }
a()函数中的函数为匿名函数,当a()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中,直到匿名函数被销毁后,a()的活动对象才会被销毁。
2. 闭包只能取得包含函数中任意变量的最后一个值。
function createFunctions(){ var result = new Array(); for(var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result;//10,10,10,10,10,10,10,10,10,10 }
每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以它们引用的都是同一个变量i。可以创建另一个匿名函数强制让闭包的行为符合预期。
function createFunctions(){ var result = new Array(); for(var i = 0; i < 10; i++){ result[i] = function(num){ return function(){ return num; }; }(i); } return result; //1,2,3,4,5,6,7,8,9 }
将变量i的值传递给num,在这个匿名函数内部,又创建并返回了一个访问num的闭包,这样result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值了。
3. this对象
在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window。
var name = "The Window"; var object = { name: "My Object", getNameFunc: function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());//"The Window"
每个函数在被调用时,其活动对象都会自动取得两个特殊变量: this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象位置(本身为1,全局为2),因此永远不能直接访问外部函数中的这两个变量。不过,把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。
var name = "The Window"; var object = { name: "My Object", getNameFunc: function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());//"My Object"
应用场景:
(1)在内存中维持一个变量。
(2)通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)