《Javascript高级程序设计》读书笔记之闭包
闭包
function createComparisonFunction(propertyName) { return function (object1, object2) { var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } }; } //创建函数 var compare = createComparisonFunction("name"); //调用函数 var result = compare({ name: "Jim" }, { name: "Jack" }); //解除对匿名函数的引用,以便释放内存 compare = null;
匿名函数从createComparisonFunction()中被返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。
这样,匿名函数可以访问在createComparisonFunction()中定义的所有变量,同时,createComparisonFunction()函数执行完毕后,其活动对象也不会被销毁,因为匿名对象的作用域链仍然引用这个活动对象。
直到匿名函数呗销毁后,createComparisonFunction()函数的活动对象才会被销毁
闭包与变量
下面代码片段中,片段1中,每个函数的作用域中都保存着createFunctions()函数的活动对象,所以他们都应用的是同一个变量i。createFunctions()函数执行完后,i为5,所以每个匿名函数内部i的值都是5
片段2中,在返回的匿名函数外部,再创建一个匿名函数,并将立即执行该匿名函数的结果赋给数组。函数参数按值传递,变量i的当前值赋值给num,匿名函数内部,创建了访问该num变量的闭包。
//代码片段1 function createFunctions() { var result = new Array(); for (var i = 0; i < 5; i++) { result[i] = function () { alert(i); } } return result; } var funcs = createFunctions(); //Array.forEach() funcs.forEach(function (item) { item(); }); //5,5,5,5,5 //代码片段2 function createFunctions() { var result = new Array(); for (var i = 0; i < 5; i++) { result[i] = function (num) { return function () { alert(num); } } (i); } return result; } var funcs = createFunctions(); //Array.forEach() funcs.forEach(function (item) { item(); }); //0,1,2,3,4
闭包中的this
var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { return function () { return this.name; } } }; alert(object.getNameFunc()()); //"The Window"
object.getNameFunc()返回一个匿名函数,在全局环境调用该函数,this指向的全局对象
解决这一问题,可以将匿名函数外部作用域中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"