关于js闭包的一些常见的问题解析

原创 zhongxiaoyou 随笔 javascript 150阅读 2018-01-26 21:55:45 举报

一、javascript 代码

答案为
a: undefined,0,0,0
b: undefined,0,1,2
c: undefined,0,1,1
思路解析:
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
1、fun(0)时,第一个参数n为0,第二个参数o未设置,console.log(o)为undefined,return值为:
{
fun:function(m){
return fun(m,n); //n为0
}
2、a.fun(1);m=1,代入上方return,得出新的return值为fun(1,0),执行得出console.log(0),return值为:
//fun(1,0) return值为:
{
fun:function(m){
return fun(m,n); //n为0
}
3、a.fun(2);m=2,同理代入上方return,得出新的return值为fun(2,0),执行得出console.log(0),return值为fun(3,0);
4、a.fun(3);m=3同理,代入上方return,得出新的return值为fun(3,0),执行得出console.log(0)。

var b = fun(0).fun(1).fun(2).fun(3);
1、与前面a一样,当执行到fun(0)时,第二个参数未设置,console.log(o)为undefined;
2、当执行到fun(0).fun(1)时,m为1,代入return,得出新的return值为fun(1,0),执行fun(1,0),console.log(0),return值为fun(1,1);
3、当执行到fun(0).fun(1).fun(2)时,m为2,代入return,得出新的return值为fun(2,1),执行fun(2,1),console.log(1),return值为(2,2)
4、当执行到fun(0).fun(1).fun(2).fun(3)时,m为3,代入return,得出新的return值为fun(3,2),执行fun(3,2),console.log(2);

var c = fun(0).fun(1); c.fun(2); c.fun(3);
1、当fun(0)时,与前面b一致,undefined;
2、当fun(0).fun(1)时,与前面b一致,console.log(0),得出新的return值为fun(1,1)
因此c.fun(2)就是fun(0).fun(1).fun(2),与前面b一致,console.log(1);
因此c.fun(3)就是fun(0).fun(1).fun(3),m=3,代入return,得出新的retrun:fun(3,1),得出结果console.log(1)

二、javascript 代码

答案为:5 5 5 5 5
思路解析::
这个定时器里面有个匿名函数且有闭包,要打印i此时调用了它外面的循环的i,当循环结束后才打印出i,所以i每次都是打印最后那个循环结束的最新值5

三、javascript 代码

答案为:456
思路解析:
其实a变量中只有1个属性 [object Object](因为只有字符串才可以做属性名),它们在通过 [] 访问对象属性时,方括号中的表达式将会被求值并被通过调用它的toString方法转换成一个字符串.此时toString = [object Object],即这里的a=123和a[c]=456分别转换成了a['[object Object]'] = 123和a['[object Object]'] = 456,所以再次赋值就会被覆盖

四、javascript 代码

答案为:a :undefined
b :number
思路解析:
因为在闭包中var声明的是局部变量,所以这里的a是局部变量,而b没有用var声明,所以在闭包中b自动变成全局变量,那因此打印的时候,由于a在这个函数的外面是没有声明而无法找到,而b在闭包里面b=3赋值了,所以输出b的类型是number

五、javascript 代码

答案为:2 4 1 1 2 3 3
思路解析:
从题目来看,getName分别以变量,和函数变量的形式声明,涉及到变量声明提前。因此实际执行是:
function Foo() {
getName = function () { alert (1); };
return this;
}
var getName;//只提前变量声明
function getName() { alert (5);}//覆盖var的声明
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};
1、因此Foo.getName()调用时,首先访问静态属性,所以返回2;
2、getName();变量声明提前,函数声明提前,函数覆盖变量声明,所以返回4;
3、Foo().getName();执行第一个函数返回的this,Foo函数中赋值一个全局变量 getName=function(){alert(1)},当前作用域没有getName,因此会向上层寻找window,覆盖外面的getName的定义,返回一个1,。同时这时也改变了全局变量,this指向了window,相当于window.getName;
4、 getName();由于前面已经将全局变量给替换掉了,所以直接调用getName();
5、new Foo.getName()相当于 new(Foo.getName)(),这里注意运算符优先级,new一个(Foo.getName),即new了一个静态方法里的 Foo.getName对象,就返回了2 。这里运用了运算符优先级,其级别表示分别为:
圆括号()>成员访问>new带参数列表>函数调用>new不带参数列表>递增递减>逻辑运算符>一元加法减法>typeof>算数>位移>比较>in,instance>条件,赋值,逗号
6、(new Foo()).getName();是关于返回值的问题。在构造函数中,返回值可以没有返回值,有返回值的时候检查是不是引用类型,是基本类型等于undefined,实例里返回实例化对象,是引用类型的时候返回undefined,实例返回这个引用类型。这里返回了this是实例化对象,没有getName属性,通过原型链找到构造函数的原型对象为3;
7、new new Foo().getName();等价于new ((new Foo()).getName)(),所以也是返回3

六、javascript 代码

答案为:441
思路解析:
1、在这里的this.value其实是原型变量,在classA函数内部定义为classA.prototype.value,它 与 var value是两个不同的变量。
2、这里第一个和第二个classa.getValue()其实都是输出的var value=4这个值,而第三个classa.value其实输出的是this.value的值,因为这个值已经被setValue赋值为1了。
3、this.value和var value=4这个value是两个不同的变量, 而this.value和(classa.value和(classa.prototype.value是同一个变量

评论 ( 2 )
最新评论
zhongxiaoyou 1F 2018-01-27 08:32:55 2F

嘿嘿嘿,谢谢

大神M 2018-01-27 08:08:02 1F

这个写的太很好,思路清晰。