闭包面试题
第一题
var test = (function (i) {
return function () {
alert(i *= 2);
}
})(2);
test(5);
上述代码结果 ‘4’
执行的过程
- 刚开始时,初始化test,由于test是一个立即执行函数,即是引用类型,故创建一个堆内存空间
- var test = ()() 代码执行时,需要执行在上下文环境下解析-》 现创建一个新的执行上下文
- test的这个堆中存储了一个形参i,i = 2, return function…
- return 的是一个函数,会创建一个新的堆来存储函数,这个堆里存有代码以及原型等,在此代码中存储了’alert(i *= 2);’,此时这个函数就指向了这个堆的地址,也就是return一个地址,比如AAAFFF111
- test指向的是立即执行函数的结果,所以test = AAAFFF111,指向这个地址,此时的test的堆里就是:i = 2,return AAAFFF111
- 接下来test(5),执行代码又创建了一个执行上下文,执行代码alert(i *= 2),由于这个栈里没有形参i的值,故到上级作用域中寻找,此时i = 2
- 得出答案 4,alert弹窗存在隐式转换,故结果是字符串‘4’
第二题
var a = 0,
b = 0;
function A(a) {
A = function(b) {
console.log(a + b++);
}
console.log(a++);
}
A(1);
A(2);
结果为:2,4
执行的过程
第三题
var x = 0,
y = 1;
function fn() {
x+=2;
fn=function (y) {
console.log(y, (--x));
}
console.log(x, y);
}
fn(3);// 2 1
fn(4); // 4 1
console.log(x, y);// 1 1
- 初始化全局变量x = 0,y = 1;
- fn(){}-> 创建一个堆存储,创建一个执行上下文,存储代码,x +=2; fn = …, cosole.log(x, y);
- fn(3) 创建一个执行上下文,执行x += 2 ,在该作用域中没有x的值,全局的x = 0,故现在x=2,fn=xxx-> 创建一个堆存储,地址为AAAFFF000,fn不是私有属性,所以改变了全局下的原来fn的指向(fn存储形参y和console.log(y, (–x))),console.log(x, y);全局下的y为1,故打印2,1
- fn(4) 创建一个执行上下文,之前fn的指向改变,所以执行代码console.log(y, (–x));此时的x = 2,y是传值来的y = 4,故打印 4,1
- 上一步骤的y是局部变量,全局下的y的值依然是1,x为2,故最后打印1 1