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

来源:互联网 发布:唐小僧 知乎 编辑:程序博客网 时间:2024/06/10 21:01

题如下,让你写出输出结果:

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();//4401console.log(result.n);//4399result2.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指向两个不同的对象(虽然表达式是相同的),有不同的作用域链