zoukankan      html  css  js  c++  java
  • 一道经典面试题-----setTimeout(function(){},0)

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

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

    先看题:

    1 for (var i = 0; i < 3; i++) {
    2     setTimeout(function() {
    3         console.log(i);
    4     }, 0);
    5     console.log(i);
    6 }

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

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

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

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

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

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

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

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

    1 setTimeout(fn, 2000)

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

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

    1 window.onload = function() {
    2         fn();
    3 }
    4 var fn = function() {
    5         alert('hello')
    6 };

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

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

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

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

    原题等价于:

     1 var i = 0;
     2 setTimeout(function() {
     3     console.log(i);
     4 }, 0);
     5 console.log(i);
     6 i++;
     7 setTimeout(function() {
     8     console.log(i);
     9 }, 0);
    10 console.log(i);
    11 i++;
    12 setTimeout(function() {
    13     console.log(i);
    14 }, 0);
    15 console.log(i);
    16 i++;

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

     1 var i = 0;
     2 console.log(i);
     3 i++;
     4 console.log(i);
     5 i++;
     6 console.log(i);
     7 i++;
     8 setTimeout(function() {
     9     console.log(i);
    10 }, 0);
    11 setTimeout(function() {
    12     console.log(i);
    13 }, 0);
    14 setTimeout(function() {
    15     console.log(i);
    16 }, 0);  //弹出 0 1 2 3 3 3

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

    1 for (var i = 0; i < 3; i++) {
    2     setTimeout((function(i) {
    3         return function() {
    4             console.log(i);
    5         };
    6     })(i), 0);  //改为立即执行的函数
    7     console.log(i);  
    8 }
  • 相关阅读:
    Android 博客园客户端 (六) OnItemLongClickListener for Blog, News and Comment
    Android 博客园客户端 (五) 查看评论、搜索博主
    Android 博客园客户端 (四) 基本功能完成(博客列表和内容、新闻列表和内容、推荐博主)
    Android 博客园客户端 (三) 博客列表和内容显示
    Android 博客园客户端 (二) 新界面&部分功能
    Android UI 之 ListView
    Git 客户端基本配置
    Android 博客园客户端 (一) 基本界面
    性能优化的心得
    重构
  • 原文地址:https://www.cnblogs.com/destinyruru/p/5823760.html
Copyright © 2011-2022 走看看