一道经典面试题-----setTimeout(function(){},0)

转载: http://www.w3cfuns.com/notes/17398/e8a1ce8f863e8b5abb530069b388a158/page/3.html#tagsbar

先看题:

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

结果是:0 1 2 3 3 3
很多公司面试都爱出这道题,此题考察的知识点还是蛮多的。
都考察了那些知识点呢?
异步、作用域、闭包。
我们来简化此题:

 setTimeout(function() {
console.log(1);
}, 0);
console.log(2); //先打印2,再打印1

因为是setTimeout是异步的。
正确的理解setTimeout的方式(注册事件):
有两个参数,第一个参数是函数,第二参数是时间值。
调用setTimeout时,把函数参数,放到事件队列中。等主程序运行完,再调用。

就像我们给按钮绑定事件一样:

 btn.onclick = function() {
alert(1);
};

这么写完,会弹出1吗。不会!!只是绑定事件而已! 必须等我们去触发事件,比如去点击这个按钮,才会弹出1。

setTimeout也是这样的!只是绑定事件,等主程序运行完毕后,再去调用。

setTimeout的时间值是怎么回事呢?

 setTimeout(fn, 2000)

程序会不会报错? 不会!而且还会准确得打印1。为什么? 因为真正去执行console.log(i)这句代码时,var i = 1已经执行完毕了!

所以我们进行dom操作。可以先绑定事件,然后再去写其他逻辑。

 window.onload = function() {
fn();
}
var fn = function() {
alert('hello')
};

这么写,完全是可以的。因为异步!

es5中是没有块级作用域的。

 for (var i = 0; i < 3; i++) {}
console.log(i); //3,也就说i可以在for循环体外访问到。所以是没有块级作用域。

这回我们再来看看原题。
原题使用了for循环。循环的本质是干嘛的?
是为了方便我们程序员,少写重复代码。

原题等价于:

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

因为setTimeout是注册事件。根据前面的讨论,可以都放在后面。
原题又等价于如下的写法:

 var i = 0;
console.log(i);
i++;
console.log(i);
i++;
console.log(i);
i++;
setTimeout(function() {
console.log(i);
}, 0);
setTimeout(function() {
console.log(i);
}, 0);
setTimeout(function() {
console.log(i);
}, 0); //弹出 0 1 2 3 3 3

怎么保证能弹出0,1, 2呢?

 for (var i = 0; i < 3; i++) {
setTimeout((function(i) {
return function() {
console.log(i);
};
})(i), 0); //改为立即执行的函数
console.log(i);
}

一道经典面试题-----setTimeout(function(){},0)的更多相关文章

  1. setTimeout(function(){}, 0);

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

  2. 关于fork的一道经典面试题

    这是一道面试题,问程序最终输出几个“-”: #include<stdio.h> #include<sys/types.h> #include<unistd.h> i ...

  3. 关于global和$GLOBALS[]的一道经典面试题

    在不执行程序的情况下,你觉得的输出结果是什么? <?php $var1 = 1; $var2 = 2; function test(){ global $var1,$var2; $var2 = ...

  4. 一道经典面试题,atoi函数的实现

    参考资料 (1)atoi函数的实现 (2)<剑指offer> 题目分析 本题需要注意的有几个方面: (1)检查输入参数,指针是否为NULL: (2)去除字符串前面的空格 (3)处理正负符号 ...

  5. java120经典面试题

    经典面试题 -----version 1.0 题注:以下答案仅限本人个人见解,若有错误和建议请多多指教.QQ:1807812486 题目来源 1.什么是Java虚拟机?为什么Java被称作是" ...

  6. for(var i=1;i<=3;i++){ setTimeout(function(){ console.log(i); },0); };答案:4 4 4。

    看面试题时,发现了一道较为经典的面试题,代码如下 for(var i=1;i<=3;i++){ setTimeout(function(){ console.log(i); },0); }; / ...

  7. 解析js中作用域、闭包——从一道经典的面试题开始

    如何理解js中的作用域,闭包,私有变量,this对象概念呢? 就从一道经典的面试题开始吧! 题目:创建10个<a>标签,点击时候弹出相应的序号 先思考一下,再打开看看 //先思考一下你会怎 ...

  8. 一道经典JS面试题

    超过80%的候选人对下面这道JS面试题的回答情况连及格都达不到.这究竟是怎样神奇的一道JS面试题?他考察了候选人的哪些能力?对正在读本文的你有什么启示? 不起眼的开始 招聘前端工程师,尤其是中高级前端 ...

  9. OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)

    摘要 本文先给出一个看似很简单实则有深意的Java笔试面试题,引出JDK内部的缓存. JDK内部的缓存,主要是为了提高Java程序的性能. 你能答对这道"看似简单,实则有深意"的J ...

随机推荐

  1. es6学习笔记11--Proxy和Reflect

    Proxy概述 Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. Proxy可以理解成,在目标对象之前 ...

  2. angularjs学习第一天笔记

    您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...

  3. C# serialPort的DataReceived事件无法触发 ,用的霍尼韦尔的扫码枪并且装了相应的USB转串口驱动。

    昨天想试试霍尼韦尔的扫码枪,扫码枪有两种模式,键盘模式和串口模式, 1.键盘模式直接插上就行了,就像一个键盘一样不需要任何驱动,扫出来的数据直接落到PC的输入焦点上.就像一个键盘一样,只能输入字符. ...

  4. Extjs4 store load 有中文字符提交后台乱码解决方法

    一.在load提交时对字符串进行decode处理. {name : encodeURIComponent(value)} 然后在后端进行反编码 java.net.URLDecoder.decode(n ...

  5. [日常] Linux下vim的常用命令总结

    vim按d表示剪切按dd剪切一行vim命令:命令模式 /关键字 n继续向下查找 vim的多行注释:1.按ctrl + v进入 visual block模式2.按上下选中要注释的行3.按大写字母I,再插 ...

  6. [日常] Go语言圣经-竞争条件习题

    package main import( "fmt" "sync" ) var balance int func Deposit(amount int) { b ...

  7. Spring IOC 容器源码分析

    声明!非原创,本文出处 Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 S ...

  8. Map集合框架的练习

    Map是一个很重要的集合框架,它以键值对的方式存储,下面是一个Map集合的小练习,使用了keySet的取出方法. 取出字符串的每一个字符,记录每一个字母出现的次数.使用Map集合框架. package ...

  9. 启动HDFS时datanode无法启动的坑

    启动HDFS 启动hdfs,进入sbin目录,也可以执行./start-all.sh - $cd /app/hadoop/hadoop-2.2.0/sbin - $./start-dfs.sh 在此之 ...

  10. js 微信支付

    引入 <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0. ...