JS 探索 this 指向问题

1. 扑朔迷离的 this

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

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

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

  1. 老早以前,this 指向它的调用者
     <script>
         // 通过 dom 调用
         var _html = document.documentElement;
         _html.onclick = function () {
             console.log("this === _html", this === _html); // true
         };
     
         // 通过 obj 调用
         var _obj = {
             getInfo: function () {
                 console.log("this === _obj", this === _obj); // true
             },
         };
         _obj.getInfo();
     
         // 直接调用
         function getInfo() {
             console.log("this === window", this === window); // true
         }
         getInfo();
     </script>
  2. 后来遇到了面试官,学会了 bind
     <script>
         // 预定义一个 dom 和 handle
         var _html = document.documentElement;
         function handle() {
             console.log(this);
         }
     
         // 预定义调用者
         var _num = ;
         var _obj = {};
         var _nul = null;
     
         // 使用 bind 绑定
         var _numHandle = handle.bind(_num);
         var _objHandle = handle.bind(_obj);
         var _nulHandle = handle.bind(_nul);
     
         // 都执行一遍
         _html.addEventListener("click", _numHandle); // Number {1}
         _html.addEventListener("click", _objHandle); // {}
         _html.addEventListener("click", _nulHandle); // Window {…}
     </script>
  3. 后来发现,如果独立调用一个函数,使用 bind 太麻烦了,学会了 call,apply,我下面用 call
     <script>
         function getInfo() {
             console.log(this);
         }
     
         // 预定义调用者
         var _num = ;
         var _obj = {};
         var _nul = null;
     
         // 用 call 调用
         getInfo.call(_num); // Number {1}
         getInfo.call(_obj); // {}
         getInfo.call(_nul); // Window {…}
     </script>
  4. 可以看到 [call, apply, bind] 绑定 this 的时候对参数做了处理,如果是 null 或 undefined,就绑定 Window;如果是简单数据类型,就用 Object 包裹一下

3. 通过“各种变通的方式”做一个推理

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

4. 结论

  1. this 指向调用者
  2. 改变 this 指向的方式是改变调用者
  3. 一路走来,真是返璞归真啊^O^
0 条评论
请不要发布违法违规有害信息,如发现请及时举报或反馈
还没有人评论呢,速度抢占沙发!
相关文章
  • 队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结...

  • 本文实例讲述了JS实现的获取银行卡号归属地及银行卡类型操作以及Luhn校验算法校验银行卡号算法。分享给大家供大家参考,具体如下: javascript代码如下 /** * Luhn校验算法校验银行卡...

  • 本文翻译自 Intercepting JavaScript Fetch API requests and responses 拦截器是可用于预处理或后处理 HTTP 请求的代码块,有助于全局错误处理、...

  • 本文简介点赞 + 关注 + 收藏 = 学会了fabric.js 的铅笔其实是继承基础画笔的一个工具,在基础画笔的基础上多了“拐角平滑度”等配置项。本文讲解铅笔的基础用法以及常用事件。常规配置真实世界的...

  • 前言 公司要求不使用JQuery,而使用原生JS。 作为一个用惯了JQuery的人来说,用原生JS的节点操作无疑是很难用的。 这篇随笔,目的是总结对比JQuery与原生JS的各种节点操作的区别。 对...

  • 为什么使用this先看个例子:function identity() { return this.name.toUpperCase(); } function speak() { r...

  • Error Error是JavaScript语言中的一个标准的内置对象,专门用于处理JS开发中的运行时错误。 当我们的JS代码在运行过程中发生错误的话,就会抛出Error对象,整个程序将会中断在错误发...

  • 一、认识函数式编程 为什么学习函数式编程?学吧,不学干啥,js太原始了,得接收新事物,就很帅,里面的概念,学的晕乎乎,最直观的感受就是,套娃 函数式编程是随着React的流行受到关注的 Vue3开始...

  • /** * 复制器 * @param {[String]} content 需要复制的内容 */ function copier(content) { let textarea = ...

  • 写在前面 模块化开发是我们日常工作潜移默化中用到的基本技能,发展至今非常地简洁方便,但开发者们(指我自己)却很少能清晰透彻地说出它的发展背景, 发展过程以及各个规范之间的区别。故笔者决定一探乾坤,深入...

  • JS逆向之补环境过瑞数详解 “瑞数” 是逆向路上的一座大山,是许多JS逆向者绕不开的一堵围墙,也是跳槽简历上的一个亮点,我们必须得在下次跳槽前攻克它!! 好在现在网上有很多讲解瑞数相关的文章,贴心的一...

  • 原型链与继承 new 关键字的执行过程 让我们回顾一下,this 指向里提到的new关键字执行过程。 创建一个新的空对象 将构造函数的原型赋给新创建对象(实例)的隐式原型 利用显式绑定将构造函数的...

  • App逆向案例 X嘟牛 - Frida监听 & WT-JS工具还原(一) 文章目录 App逆向案例 X嘟牛 - Frida监听 & WT-JS工具还原(一) 前言 一、资源推荐...

  • 203.移除链表元素 题目链接: https://leetcode.cn/problems/remove-linked-list-elements/ 题目描述: 给你一个链表的头节点 head 和一个...

  • 〇、简介 椭圆曲线密码学(Elliptic curve cryptography:ECC),一种建立公开密钥加密的演算法,基于椭圆曲线数学。利用有限域上椭圆曲线的点构成的 Abel 群离散对数难解性,...

  • 回调地狱是由于多个回调函数嵌套引起的: 回调函数:一个函数以参数的形式传入另一个函数。如: $.post(url,function(data){ }) 回调地狱: 上面那个是嵌套了一层,好像看上去很正...

  • 首先我们知道JavaScript引擎包括一个调用栈和堆,调用栈是代码实际执行的地方,使用执行上下文(执行环境)来完成;堆是非结构化的内存池,存储了应用程序所需要的所有对象。 执行上下文是什么? 执行上...

  • JavaScript 中,对于普通对象,不能直接使用 length 来获取对象的长度,因为 JavaScript 对象并不是一种有序的集合,没有长度的概念。 对于数组或者类数组对象,可以使用 .len...

  • 案例介绍 欢迎来的我的小院,我是霍大侠,恭喜你今天又要进步一点点了!我们来用JavaScript编程实战案例,做一个乘法积分游戏。乘法游戏主要通过用户输入的数值和程序计算的数值进行对比,正确积一分,错...

  • 本文简介点赞 + 关注 + 收藏 = 学会了还记得当初学 CSS 时,有点基础后立刻就想搞点动画出来玩一下。在了解了 Three.js 的基础概念之后也有这个想法。简单的动画可以提高 Three.js...