一道有趣的js题以及个人的理解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一道有趣的js题以及个人的理解相关的知识,希望对你有一定的参考价值。

var number = 2;
var obj = {
  number : 4,
  fn1 : ( function() {     
    this.number *= 2;
    number=number*2;
    var number=3;
    return function() {
      this.number *= 2;
      number*=3;
      alert(number);
    } 
  } )(),
  db2:function(){this.number*=2}
};
var fn1 = obj.fn1;
alert(number);//问这会会弹出什么结果 4
fn1();//这会弹出什么结果 9
obj.fn1();//这次弹出什么结果 27
alert(window.number); //这会window.number的结果是什么 8 
alert(obj.number);   //这会obj.number的结果是什么 8

  这是我无意间看到的一道js题,当时理解了好久,不过总算明白了,下面附上自己的解析。

一、编译阶段

var number = 2;
var obj = {
  number : 4,
  fn1 : ( function() {     
    this.number *= 2;
    number=number*2;
    var number=3;
    return function() {
      this.number *= 2;
      number*=3;
      alert(number);
    } 
  } )(),
  db2:function(){this.number*=2}
};
先看以上这段代码,其中包括了一个IIFE(Immediately-Invoked Function Expression )立即执行函数表达式(function(){})()。这个函数在编译阶段就执行了。主要作用是隔离作用域,模仿块级作用域。
为了方便理解,我在代码中添加alert();
var number = 2;
var obj = {
  number : 4,
  fn1 : ( function() {     
    this.number *= 2;
    alert(this);  //window
    number=number*2;
    alert(number);  //NAN  原因:变量声明提前
    var number=3;
    alert("执行");
    return function() {
      this.number *= 2;
      number*=3;
      //alert(number);
    } 
  } )(),
  db2:function(){this.number*=2}
};
可以看到IIFE的function的this指向的是window,并且在函数编译阶段就执行了,所以运行以上代码就会依次打印:
window 
NAN 
执行
并且 全局number=4; 
     obj.number=4;
     IFFE 中存在的var number=3;(由于闭包的存在使IIFE的活动对象仍会存在)
二、执行阶段
var fn1 = obj.fn1;
alert(number);//问这会会弹出什么结果 4
fn1();//这会弹出什么结果 9
obj.fn1();//这次弹出什么结果 27
alert(window.number); //这会window.number的结果是什么 8 
alert(obj.number);   //这会obj.number的结果是什么 8
1、var fn1 = obj.fn1;使fn1指向了IFFE的闭包,闭包的存在
2、alert(number);//此时是指全局number=4;
3、fn1();//调用fn1()函数,闭包中this的原则是是哪个对象调用该函数,this就指向哪个对象。此时是window对象调用。因此,
this.number 是指全局number(既是变量也当作window属性),全局 number=8;
变量的number根据作用域链以及闭包的规则,优先在内部环境找(无),再往上一级找(匿名函数中 var number=3 有) 所以var number=9;所以再alert(number)就为9。
4、obj.fn1();//obj调用fn1,obj.number=8,变量的number根据作用域链以及闭包的规则,优先在内部环境找(无),再往上一级找(匿名函数中 var number=9 有) 所以var number=27;所以再alert(number)就为27。
5.此时window.number=8;
6.此时obj.number=8;
 
重点:
理解IIFE的隔绝作用域,理解闭包的作用域链。

以上是关于一道有趣的js题以及个人的理解的主要内容,如果未能解决你的问题,请参考以下文章

奇妙JS代码系列一道有趣的题(创建一个长度为x数组)

一道有趣的面试题

一道有趣的签到题

一道有趣的面试题

一道经典面试题:字符串在Java中如何通过“引用”传递

浅析一道有趣的数组题