博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端计划——一道经典的JavaScript问题(含闭包、事件轮询、作用域等概念解释)...
阅读量:6174 次
发布时间:2019-06-21

本文共 2026 字,大约阅读时间需要 6 分钟。

前言:这是一道很经典的Js面试题,涉及到闭包、变量作用域、setTimeout等知识,对于深入理解这些内容很有帮助

题目描述

//问题描述:请写出最终的输出值,并解释原因var value1 = 0, value2 = 0, value3 = 0;for ( var i = 1; i <= 3; i++) {    var i2 = i;    (function() {        var i3 = i;        setTimeout(function() {            value1 += i;            value2 += i2;            value3 += i3;        }, 1);    })();}setTimeout(function() {    console.log(value1, value2, value3);}, 100);
//输出结果:value1=12; value2=9; value3=6

题目解释

首先,为了下面解释这道题,我们先来补充一些预备知识(大神级人物可跳过这部分)

一、基础知识补充与温习

1、闭包和作用域

官方解释:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

function a(){    var i=0;    function b(){        alert(++i);    }    return b;}var c=a();c();

方言版:当函数a的内部函数b被外部变量c引用时,就形成了闭包

闭包的作用:我们知道,js里定义在函数内部的是局部变量,外部是无法直接访问的,而它的内部函数可以访问,那么内部函数返回一个值,就相当于类似在外部也能访问局部变量。

闭包的特点:为了使b中能够访问i的值,i不会被内存回收,就实现了内存常驻。对于理解这道题很重要。

闭包的缺点:内部闭包函数可以访问外部函数的变量,所以外部函数的变量不能被释放,如果闭包嵌套过多,会导致内存占用大,出现内存溢出。

作用域和作用域链:关于作用域这里不做过多解释,js中根据作用域可分为全局变量和局部变量。而对于作用域链的简单理解,可以认为当一个函数创建之后,从它的执行环境(当前对象)一直到全局对象建立了一个链表,可用的变量都挂载在上面。而函数需要查找某个变量值时,变回按照从当前直到全局对象来进行查找。

2、事件轮询与setTimeout

简介:setTimeout是js中常见的一个函数,属于window下的方法(通常,大家会省略window)

语法:setTimeout(code,millisec) 参数一为代码,参数二为毫秒数
作用:设定一个时间, 时间到了之后, 就会执行一个指定的函数或表达式,且只执行一次。

好吧,setTimeout不是这部分核心,核心是解释js的单线程和事件轮询机制。

我们知道,js是单线程的,也就是说所有的任务要排队执行。
在js中有同步和异步执行——
同步执行:是指前一个任务执行完,然后下一个任务继续执行,都在主线程里。
异步执行:则是把事情放进“任务队列”(或叫事件队里),而不是在主线程中,它们通过事件轮询(Event Loop)和回调来实现调入主线程执行。
继续回到setTimeout,语法里面的code就是异步执行的部分。
关于setTimeout更详细的内容,可点击这里学习
关于事件轮询的学习,请点击这里

二、对习题的解答

上面都是些基础知识,接下来进入正题。

首先,我们拿到题目,要注意到第一个setTimeout里面匿名函数,这部分其实是放在for循环之后才会执行的,因为它是一个异步执行的函数,被放到了事件队列里最后执行。而且,每次setTimeout里面的函数执行时可以近似理解为是一次实例化。

  1. value1

    在计算value1时,需要用到i,这里涉及到作用域链的知识,最内层的函数没有i的值,它会沿着链式结构一直向上查找,最终发现i是for循环执行之后的值。此时,i的循环完成,最后一次i++之后,i已经变成了4。这样,setTimeout执行3次实例化,每次i的值是不变的,最终值为value1=4+4+4=12。

  2. value2

    类似于value1,在执行setTimeout里的函数时,需要找到i2的值,最终我们找到的是for循环到第三次时i2=i=3。(i2不会等于4,因为到最后一次i++之后,已经不会再进入循环体了)。所以类似上面,value2的值是3+3+3=9。

  3. value3

    这部分就涉及到闭包的理解了。在循环过程中,通过立即执行函数创建了闭包,每次i3都会被赋予当次循环时i的值并保存,i3的值依次为1,2,3,最终value3=1+2+3=6。

以上为个人解释,如有错误,还望各位指正。

转载地址:http://vmqba.baihongyu.com/

你可能感兴趣的文章
如何在VMware安装Windows系统
查看>>
阶段性理解phantomjs/selenium/casperjs
查看>>
Java中高级开发工程师是什么技术水平(附28套Java进阶+高级视频教程)
查看>>
sudo命令
查看>>
第十九章 文本处理流编辑器:awk编程
查看>>
Xtrabackup+Rsync 备份数据库并同步到远端备份机
查看>>
activiti实战读书笔记——第九章 多实例
查看>>
php返回相对时间(如:20分钟前,3天前)的方法
查看>>
WilliamChart各种图表效果实现大全《IT蓝豹》
查看>>
shell脚本——linux主机监控
查看>>
eclipse配置jsp页面模板
查看>>
基于高德地图写的不同功能的地图应用
查看>>
DHCP服务器配置
查看>>
快速瓶颈识别
查看>>
运维工作总结201403
查看>>
我是菜鸟我加油……mysql主从同步
查看>>
[体系结构]设计模式(五)
查看>>
分布式文件系统
查看>>
其实很简单 微星为你详解Z77主板BIOS设置
查看>>
在Ubuntu Kylin下安装JDK1.8
查看>>