• 一道经典JS题(关于this)


    项目中碰到的问题,以前也碰到过,没有重视,现记录如下。

    <input type='button' value='click me' id='btn' />
    <script>
      var num = 0;
    
      var obj = {
        num: 1,
    
        fn: function() {
          console.log(this.num);
        },
    
        init: function() {
          setTimeout(this.fn, 0);
    
          document.getElementById('btn').addEventListener('click', this.fn, false);
        }
      };
    
      obj.init();
    </script>
    

    输出啥?点击 button 后输出啥?

    解决类似的问题其实很简单,只需要牢记下面一句话:

    除了 DOM 的事件回调或者提供了执行上下文(call、apply、bind)的情况,函数正常被调用(不带new)时,里面的 this 指向的是全局作用域。

    先看第一处,其实可以改写成这样:

    setTimeout(function() {
      console.log(this.num);
    }, 0);
    

    0ms后 函数正常被调用,里面的 this 指向全局作用域 window,所以输出即为 window.num,即为代码最开始定义的 num=0。

    再看第二处,可以改写成这样:

    document.getElementById('btn').addEventListener('click', function() {
      console.log(this.num);
    }, false);
    

    click 后触发一个回调函数,属于 DOM事件回调DOM 事件回调中的 this 指向该 DOM 元素。所以输出 this.num 即为 document.getElementById('btn').num,为 undefined。

    如何能让 click 事件后输出 1?因为这种需求在生产中很常见,绑定各种事件,回调已经定义的对象方法。很明显,归根结底需要改变函数中 this 指向。

    方法一:

    再加一层匿名函数,使得 fn 被 obj 调用:

    var that = this;
    document.getElementById('btn').addEventListener('click', function() {
      that.fn();
    }, false);
    

    方法二:

    bind 改变 this 指向:

    // 兼容IE
    Function.prototype.bind = Function.prototype.bind || function(context) {
      var that = this;
      return function() {
        return that.apply(context, arguments);
      }
    }
    
    document.getElementById('btn').addEventListener('click', this.fn.bind(this), false);
  • 相关阅读:
    Python 学习记录1
    IL 汇编学习笔记(四)
    Petshop 4 学习
    MSN robot 开发相关资料
    MSDN 中文网站的某些翻译简直让人抓狂
    GridView 中如何给删除按钮添加提示
    MSDTC 分布式事务无法启动
    IL 汇编学习笔记(一)
    ASP.NET 2.0 之 Master Page 学习笔记
    IL 汇编学习笔记(二)
  • 原文地址:https://www.cnblogs.com/lessfish/p/5086960.html
Copyright © 2020-2023  润新知