对于闭包的理解首先需要对作用域的进行了解,其中最重要的一点是对于JS函数运行在它们被定义的作用域里而不是被执行的作用域里:
function f1() {
var a = 1;
f2();
function f2() {
alert(a);
}
}
f1();代码一
function f1() {
var a = 1;
f2();
}
function f2() {
alert(a);
}
f1();代码二
代码一显示a=1,代码二显示a未定义。
闭包:指外部函数无法获得内部函数的值,但内部函数的下一级可以获得并返回。
一.关于this:举连个例子:
1.
function Hero(name) { this.name = name; } var h = Hero("pcd"); var h = new Hero("pcd");
不使用new时,h值为该函数的返回值,为undefined,this指向全局变量window。
但创建一个对象时,this指向这个对象。
2.
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
}
}
}
console.log(object.getNameFunc()());
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
var that = this;
return function() {
return that.name;
}
}
}
console.log(object.getNameFunc()());
当函数被作为某个对象的方法调用时,this指向那个对象,在全局函数中this等于window。
二.
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,? var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,? var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?
答案为:
//答案: //a: undefined,0,0,0 //b: undefined,0,1,2 //c: undefined,0,1,1
return fun(m,n)为立即执行函数;匿名函数对fun活动对象的引用。
题目详解链接:http://www.cnblogs.com/xxcanghai/p/4991870.html
三.模拟块级作用域
javascript内有块级作用域,例:
if(true) { var color = "blue"; } console.log(color);//blue for (var i=0; i < 5; i++){ console.log(i); } console.log(i);//5
在函数中造成在存在该值,例:
function outputNumbers(count){ for (var i=0; i < count; i++){ console.log(i); } console.log(i); //count } outputNumbers(5);
为了使outputNumbers()中的其他地方不在有i值,将其放入模拟块级作用域中
function outputNumbers(count){ (function() { for (var i=0; i < count; i++){ console.log(i); } })(); console.log(i); //错误 }
则在outputNumbers()中的其他地方不存在有i值。
四.内存泄露
function assignHandler() { var element = document.getElementById("some_element"); element.onclick = function() { alert(element.id); } }
这是一个简单的闭包,作用域中保存着一个HTML元素,造成循环引用,导致该对象无法被销毁。
function assignHandler() { var element = document.getElementById("some_element"); var id = element.id; element.onclick = function() { alert(id); } element = null; }
创建一个id为非Dom元素,消除循环引用。
七.闭包造成内存积累
function F() { var arr = [], i; for(i = 0; i < 3; i++) { arr[i] = function() { return i; } } return arr; } var arr = F(); arr[0];//3 arr[1];//3 arr[2];//3
执行arr[0],arr[1],arr[2]时return的i已经是for循环结束之后,for没有块级作用域,此时的i为3。
function setup(x) { var i = 0; return function() { return x[i++]; } } var next = setup(['a', 'b', 'c']); next();//a next();//b next();//c
在执行next()时,return x[i++];中的i是从return function() {}这个局部内获得的,因为是闭包,造成i的累加。