下面是自己积累的几道经典JS闭包题
每一道都很有代表性,可能有的题解释的不到位,大家可以参考着结果先自己想一想,如果能够把这几道闭包题搞清楚,那么你在函数闭包上的成长一定是很大的
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript">
//代码片段一
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return this.name;
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()); //My Object 对象的方法的this指向的是对象本身
//代码片段二
var name2 = "The Window";
var object2 = {
name2: "My Object",
getNameFunc: function() {
return function() {
return this.name2;
};
}
};
console.log(object2.getNameFunc()()); //The Window
//对象的方法里的函数, 不管套了多少层, 都只是普通函数, 都指向window
//代码片段三
function fun(n, o) {
console.log(o)
return {
fun: function(m) {
return fun(m, n)
}
}
}
var a = fun(0); //undefined
a.fun(1); //0
a.fun(2); //0
a.fun(3); //0
var b = fun(0).fun(1).fun(2).fun(3); //undefined 0 1 2
var c = fun(0).fun(1); //undefined 0
c.fun(2); //1
c.fun(3); //1
//这道题实在太多经典,如果能把这道题的运行过程搞懂,那么闭包,你见到其他题,应该都没问题了
//由于这道题的运行过程是在过于繁琐,不在这里多讲,大家先自己试着运行一下,实在还有问题的话,我再好好讲一下,
//如果自己能够运行明白的话,对于自己在闭包上的成长绝对是很大的
//代码片段四
function Foo() {
getName = function() {
alert(1);
}
return this;
}
Foo.getName = function() {
alert(2);
}
Foo.prototype.getName = function() {
alert(3);
}
var getName = function() {
alert(4);
}
function getName() {
alert(5);
}
//请写出以下输出结果:
Foo.getName(); //2 Foo当对象调用getName方法,答案很明显是输出2
getName(); //4 直接调用getName函数,这里有两个,最后两个都是,不过按顺序执行,所以输出4
Foo().getName(); //1 调用Foo函数,并执行getName函数,明显输出1,
//不过值得注意的是,Foo函数return this,由于Foo里的getName函数没有带var,直接把全局的getName函数给修改了,
//所以现在全局的getName函数的值已经变成了1
getName(); //1 现在再调用getName,值已经变为1
new Foo.getName(); //2 注意!!!这里的new完全是一个烟雾弹,就是用来迷惑人的,其实还是Foo当对象调用getName方法输出2
new Foo().getName(); //3 这里才是new一个Foo实例,并调用实例的getName方法,由于自身没有,会去原型对象身上找,输出的是3
new new Foo().getName(); //3 这里的两个new,第一个new,没有任何作用,因为它和它后面的new不能执行,只能让后面new先去执行,
//我们发现后面的new能够执行,和上一个执行结果是一样的,至于第一个new,实际上没有什么意义
//代码片段五
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
console.log(Counter.value()); //0 调用value打印1
Counter.increment(); //执行changeBy函数,结果为1
Counter.increment(); //再次执行changeBy函数,结果为2
console.log(Counter.value()); //2 现在调用value,因为闭包的存在,自身没有,向上找,此时privateCounter的值为2
Counter.decrement(); //再次执行changeBy函数,结果为1
console.log(Counter.value()); //1 因为闭包的存在,自身没有,向上找,此时privateCounter的值为1
//代码片段六
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var Counter1 = makeCounter(); //这是两个独立的闭包它俩之间没有任何关系
var Counter2 = makeCounter(); //这是两个独立的闭包它俩之间没有任何关系
console.log(Counter1.value()); //0
Counter1.increment(); //1
Counter1.increment(); //2
console.log(Counter1.value()); //2
Counter1.decrement(); //1
console.log(Counter1.value()); //1
console.log(Counter2.value()); //0
</script>
</body>
</html>