JS 探索 this 指向问题

  • JS 探索 this 指向问题已关闭评论
  • 14 次浏览
  • A+
所属分类:Web前端
摘要

从表面来看,this 总能通过各种变通的方式得到意想不到的结果既然是“意想不到”,就说明对“各种变通的方式”不太了解


1. 扑朔迷离的 this

  1. 从表面来看,this 总能通过各种变通的方式得到意想不到的结果

  2. 既然是“意想不到”,就说明对“各种变通的方式”不太了解

  3. 那么我们来看看“各种变通的方式”

    1. 老早以前,this 指向它的调用者
       1 <script>  2     // 通过 dom 调用  3     var _html = document.documentElement;  4     _html.onclick = function () {  5         console.log("this === _html", this === _html); // true  6     };  7   8     // 通过 obj 调用  9     var _obj = { 10         getInfo: function () { 11             console.log("this === _obj", this === _obj); // true 12         }, 13     }; 14     _obj.getInfo(); 15  16     // 直接调用 17     function getInfo() { 18         console.log("this === window", this === window); // true 19     } 20     getInfo(); 21 </script>

    2. 后来遇到了面试官,学会了 bind
       1 <script>  2     // 预定义一个 dom 和 handle  3     var _html = document.documentElement;  4     function handle() {  5         console.log(this);  6     }  7   8     // 预定义调用者  9     var _num = 1; 10     var _obj = {}; 11     var _nul = null; 12  13     // 使用 bind 绑定 14     var _numHandle = handle.bind(_num); 15     var _objHandle = handle.bind(_obj); 16     var _nulHandle = handle.bind(_nul); 17  18     // 都执行一遍 19     _html.addEventListener("click", _numHandle); // Number {1} 20     _html.addEventListener("click", _objHandle); // {} 21     _html.addEventListener("click", _nulHandle); // Window {…} 22 </script>

    3. 后来发现,如果独立调用一个函数,使用 bind 太麻烦了,学会了 call,apply,我下面用 call
       1 <script>  2     function getInfo() {  3         console.log(this);  4     }  5   6     // 预定义调用者  7     var _num = 1;  8     var _obj = {};  9     var _nul = null; 10  11     // 用 call 调用 12     getInfo.call(_num); // Number {1} 13     getInfo.call(_obj); // {} 14     getInfo.call(_nul); // Window {…} 15 </script>

    4. 可以看到 [call, apply, bind] 绑定 this 的时候对参数做了处理,如果是 null 或 undefined,就绑定 window;如果是简单数据类型,就用 Object 包裹一下

2. 通过以上经验做一个推理

  1. this 本来指向它的调用者
  2. 通过 [call, apply, bind] 可以改变 this 指向
  3. 有没有可能是改变了“调用者”,所以 this 指向了新的“调用者”
  4. 这里是我的另一篇文章,手动实现 [call, apply, bind],它的实现方式就是改变“调用者”
  5. 可以尝试手动实现箭头函数

3. 结论

  1. this 指向调用者
  2. 改变 this 指向的方式是改变调用者
  3. 一路走来,真是返璞归真啊^O^