zoukankan      html  css  js  c++  java
  • setInterval/setTimeout 中this无效

    The execution context, this

    The button below should change it’s value to ‘OK’, but it doesn’t work. Why?

    <input type="button"
    onclick="setTimeout(function() { this.value='OK' }, 100)"
    value="Click me"
    >

    The reason is wrong this. Functions executed by setInterval/setTimeout have this=window, orthis=undefined in ES5 strict mode.  也就是说this指向了window。

    The reference is usually passed through closure. The following is fine:

    <input id="click-ok" type="button" value="Click me">
    <script>
    document.getElementById('click-ok').onclick = function() {
    var self = this
    setTimeout(function() { self.value='OK' }, 100)
    }
    </script>

    http://javascript.info/tutorial/settimeout-setinterval

    在Javascript里,setTimeout和setInterval接收第一个参数是一个字符串或者一个函数,当在一个对象里面用setTimeout延时调用该对象的方法时

    function obj() {
      this.fn = function() {
        alert("ok");
        console.log(this); 
        setTimeout(this.fn, 1000);//直接使用this引用当前对象
      }
    }
    var o = new obj();
    o.fn();

     然后我们发现上面的代码不是想要的结果,原因是setTimeout里面的this是指向window,所以要调用的函数变成 window.fn 为undefined,于是悲剧了。所以问题的关键在于得到当前对象的引用,于是有以下三种方法

    // 方法一:
    
    function obj() {
      this.fn = function() {
        alert("ok");
        console.log(this);
        setTimeout(this.fn.bind(this), 1000);//通过Function.prototype.bind 绑定当前对象
      }
    }
    var o = new obj();
    o.fn();

    这样可以得到正确的结果,可惜Function.prototype.bind方法是ES5新增的标准,测试了IE系列发现IE6-8都不支持,只有IE9+可以使用。要想兼容就得简单的模拟下bind,看下面的代码

    // 方法二:
    function obj() {
      this.fn = function() {
        alert("ok");
        setTimeout((function(a,b){
          return function(){
            b.call(a);
          }
        })(this,this.fn), 1000);//模拟Function.prototype.bind
      }
    }
    var o = new obj();
    o.fn();

    首先通过一个自执行匿名函数传当前对象和对象方法进去,也就是里面的参数a和b,再返回一个闭包,通过call方法使this指向正确。下面是比较简洁的方法

    // 方法三:
    function obj() {
      this.fn = function() {
        var that = this;//保存当前对象this
        alert("ok");
        setTimeout(function(){
          that.fn();
        }, 1000);//通过闭包得到当前作用域,好访问保存好的对象that
      }
    }
    var o = new obj();
    o.fn();

    上面第三个方法的两个关键点是 保存当前对象this为别名that 和 通过闭包得到当前作用域,以访问保存好的对象that;当对象方法里面多层嵌套函数或者setTimeout,setInterval等方法丢失this(也就是this不指向当前对象而是window),所以在this指向正确的作用域保存var that = this就变得很实用了

    原文地址:http://www.cnblogs.com/Hodor/archive/2012/07/20/2600428.html

  • 相关阅读:
    Arduino语法-变量和常量
    Arduino-函数库和程序架构介绍
    第十章浮力题汇总
    pyqt5-按钮基类-QAbstractButton
    在Windows上安装Arduino-IDE
    Arduino-接口图
    python-文件及文件夹操作
    Qt WebRTC demo
    多线程使用信号量sem_init,sem_wait,sem_post
    华为公司内部培训资料_介绍RTSP的消息、信令等
  • 原文地址:https://www.cnblogs.com/youxin/p/2697526.html
Copyright © 2011-2022 走看看