您的位置:首页 > Web前端 > JavaScript

[置顶] 谈谈一道js笔试题,涉及作用域链、闭包

2017-11-09 15:58 232 查看
题如下,让你写出输出结果:

function test(){
var n=4399;
function add(){
n++;
console.log(n);
}
return {n:n,add:add}
// 一个匿名变量

}
var result=test(); //
var result2=test();//
result.add();//4400
result.add();//4401
console.log(result.n);//4399
result2.add();4400


先说说return {n:n,add:add},可能一开始看到很懵逼,其实这就是一个匿名对象。冒号前面的n是属性名,后面的n是值。并且属性n的值n是一个number,也就是基本类型,它是不会变的,除非被重新赋值!!!但是add的值也就是add函数,是引用类型值,是会随着函数的多次调用,而改变其结果。

var result=test();这里的test()就是得到了return的{n:n,add:add},并将该值存入result的堆内存。这时的n值还是4399,为什么不是4400呢,不是有n++吗?很简单,因为add函数没有被调用过,因此n没有+1。

var result2=test();基本与上面相同,不同的是存入了不同的堆内存。因此,result和result2相互独立。

这里多说一句,如果是:var result2=result; 则result2的值不是纯粹的{n:n,add:add},而是存着指向{n:n,add:add}的指针,因此result和resut2指向同一个对象,是相互影响的。

result.add(); 调用了add函数,n++执行了,所以是4400。注意,这里的add函数是闭包,保存了自己的作用域链。add中的要用的n值是test函数中的n值,即向上追溯作用域链。

因此,这里的add函数可以等价于

function add(){
var n=4399;
n++;
console.log(n);

}

result.add(); 结果4401,不解释了。

console.log(result.n) 还是4399,刚才说了,属性n存的是基本类型值,不变。

result2.add(); 因为result和result2指向两个不同的对象(虽然表达式是相同的),有不同的作用域链
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: