美文网首页
关于js闭包的一些常见的问题解析

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

作者: 深漂浪子 | 来源:发表于2019-06-03 15:26 被阅读0次

一、javascript 代码

    function fun(n,o) {
        console.log(o);
        return {
            fun:function(m){
                return fun(m,n);
            }
        };
    }
    var a = fun(0);a.fun(1);a.fun(2);a.fun(3); 
    var b = fun(0).fun(1).fun(2).fun(3); 
    var c = fun(0).fun(1);c.fun(2);c.fun(3);

答案为
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 代码

 for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, 0);
    }

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

三、javascript 代码

 var a={};
    var b={key:'b'};
    var c={key:'c'};

    a=123;  // toString = [object Object]
    // console.log(a);  //{[object Object]: 123}
    a[c]=456;
    console.log(a);  //456

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

四、javascript 代码

(function(){
        var a = b = 3;
    })();//函数自调

    console.log("a :" + typeof a);//a :undefined
    console.log("b : " + typeof b);//b : number

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

五、javascript 代码

    function Foo() {
        getName = function () {           alert (1);        };
        return this;
    }
    // 静态方法   只能通过 Foo.方法名()
    Foo.getName = function () {   alert (2);  };
    Foo.prototype.getName = function () {  alert (3);  };
    var getName = function () {    alert (4);  };
    function getName() {  alert (5);  }

    Foo.getName();   // 2
    getName();  // 4
    Foo().getName(); // 1
    getName();  // 1
    new Foo.getName(); // 2
    new Foo().getName();  // 3
    new new Foo().getName();  // 3

答案为: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 代码

function ClassA(){
    var value = 4;
    this.getValue = function (){
        return value;
    }
    this.setValue = function (value){
        this.value = value;
    }
}

var classa = new ClassA();
document.write(classa.getValue());  // 4 
classa.setValue(1);   // 给对象classa添加了一个属性 value 他的是 1

document.write(classa.getValue());  // 4  
document.write(classa.value);  // 1  

答案为: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是同一个变量

相关文章

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

    一、javascript 代码 答案为a: undefined,0,0,0b: undefined,0,1,2c:...

  • 再谈JS闭包(JS闭包系列2)

    这篇文章,来继续谈谈Javascript闭包的剩余问题。因为在上一篇文章中关于JS闭包(JS闭包系列1)主要简单的...

  • JS闭包问题(二)

    在之前的JS闭包问题(一)文章中大概介绍了一下JS闭包,同时讲了闭包与变量之间的问题,今天我们继续聊闭包,聊聊闭包...

  • JS闭包

    JS闭包 在stackoverflow看到的一个关于闭包的问题,讲的很透彻。原问题大概是:一个包含setTimeo...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • JS闭包入门

    最近有看到朋友的面经里提到的JS闭包的问题,就想研究研究,以下是我对JS闭包的简单理解。 到底什么是JS闭包? 定...

  • 闭包,作用域链,垃圾回收,内存泄露

    1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --《JS高级程序设计...

  • 了解闭包 作用域链 垃圾回收机制

    1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --《JS高级程序设计...

  • JS闭包解析

    一、什么是闭包 闭包指能够访问另一个函数作用域的变量的函数,一般是定义在外层函数中的内层函数。例: 解析1: ou...

  • JavaScript解析机制与闭包原理实例详解

    本文实例讲述了JavaScript解析机制与闭包原理。分享给大家供大家参考,具体如下: js解析机制: js代码解...

网友评论

      本文标题:关于js闭包的一些常见的问题解析

      本文链接:https://www.haomeiwen.com/subject/devcxctx.html