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

一、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是同一个变量

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容