一道有趣的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的隔绝作用域,理解闭包的作用域链。

时间: 2024-08-27 15:08:12

一道有趣的js题以及个人的理解的相关文章

一道有趣的算法题。。。

题目意思: 用1, 2, 3 ,4 ,5, 6, 7, 8, 9 组成3个三位数 abc, def 和 ghi, 每个数字恰好使用一次,要求abc:def:ghi = 1:2:3.输出所有解. 分析: 模拟所有三位数,判断条件有二: 一.i(abc):j(def):k(ghi)=1:2:3 二.判断是否出现的1~9之间的所有数字 代码: /** *一道有趣的算法题 * */ #include<iostream> #include<cstdio> using namespace st

一道有趣的算法题:仿照Excel的列编号,给定一个数字,输出该列编号字符串

       By Long Luo 最近遇到一个算法题: 仿照Excel的列编号,给出一个数字,输出该列编号字符串. 例如:A对应1,Z对应26,AA对应27,AZ对应52 ...... 这个题目是一个典型的26进制思路去处理,但是这个题目里面有很多陷阱,在1, 26, 52等特殊情况进行考虑,经过晚上接近1个小时的编写,完成的代码如下: C++代码如下: #include <iostream> #include <string.h> using namespace std; /

BOBSLEDDING(一道有趣的贪心题 nyoj309)

BOBSLEDDING 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 Dr.Kong has entered a bobsled competition because he hopes his hefty weight will give his an advantage over the L meter course (2 <= L<= 1000). Dr.Kong will push off the starting line at 1 meter per

一道有趣的签到题

题目链接 题目描述 写一个程序,使其能输出自己的源代码. 代码中必须至少包含十个可见字符. 输入格式 输入文件为空. 输出格式 你的源代码. 从来没想过还可以这么玩φ(゜▽゜*)? 看着别人的题解写了一份代码: #include<bits/stdc++.h> #define kk(x) #x using namespace std; char s[]=kk(int main(){puts("#include<bits/stdc++.h>");puts("

一道js题

<script> var a = 5; function test(){ this.a = 10; a = 15 this.func = function(){ var a = 20 ; alert(this.a); } } var tt = new test(); tt.func(); setTimeout(tt.func, 1000); </script> 这是之前看到的一道js题,其中有a出现了五次,那么到底输出什么呢,我想看了我上一个随笔你应该就明白了. 这个题主要考察两个

有趣的Js Quiz,测测你的Core Js内功

最近看国外同行的技术博客, 看到一篇有关"javascript小测试"的博文, 很有意思, 其中每个题目短小精悍, 却能很好的考察对 Core Javascript的掌握深度.如果你感兴趣,可以点击JavaScript Quiz查看原文, 为了做个记录, 我准备在下文罗列出这些题目, 并给出解释, 如果有解释不到位的地方, 欢迎园友指出. 首先有几个要注意的地方: 以下题目采用ECMA3标准(不是5) quirks模式的实现不予考虑 每个代码片段的running context都是gl

一道模板元编程题源码解答(replace_type)

今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: 类型就是数据. 题目如下所述: Write a ternary metafunction replace_type<c,x,y> that takes an arbitrary compound type c as its first parameter, and replaces all oc

考考你!一道有趣的Javascript小题目

今天的内容很简单,给大家分享一个有趣的Javascript小题目. 题目很简单,就是填空: var a = ______; var b = a;alert(a==b); // alert "false" 请将程序补充完整,使得弹出的对话框显示为"false". 先答出的有奖哦 ^ ^ --------------------- 用简单而风趣的形式表达出自己的想法是我一直追求的目标(当然,目前还处于"XX主义初级阶段",还有很长的路要走). 如果你

一个简单有趣的证明题

最近上算法课,老师讲了一个有趣的证明题. 平面上一个有n个点的有限点集A.具有如下性质:任意两个点x,y所决定的直线上都能找到第三个点z.试证明A中的所有点在同一直线上. 对于证明题来说,最常用而系统的方法无非就两种:归纳法和反证法.其他的诸如综合法和分析法都与具体问题关系较大.如果解决证明题一时没有思路,这两种方法将是不错的选择.下面将尝试用这两种方法解决这个题目. 一,归纳法. 相信学过高中数学的人,没有人不知道这个大名鼎鼎,而又简单有效的证明方法.这里就不再赘述.下面给出一个证明过程. (