this的绑定规则总共有下面5种。

  • 1、默认绑定(严格/非严格模式)

  • 2、隐式绑定

  • 3、显式绑定

  • 4、new绑定

  • 5、箭头函数绑定

1 调用位置

调用位置就是函数在代码中被调用的位置(而不是声明的位置)。

查找方法:

分析调用栈:调用位置就是当前正在执行的函数的前一个调用中

  • 使用开发者工具得到调用栈:

    设置断点或者插入debugger;语句,运行时调试器会在那个位置暂停,同时展示当前位置的函数调用列表,这就是调用栈。找到栈中的第二个元素,这就是真正的调用位置。

2 绑定规则

2.1 默认绑定

  • 独立函数调用,可以把默认绑定看作是无法应用其他规则时的默认规则,this指向全局对象。

  • 严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined。只有函数运行在非严格模式下,默认绑定才能绑定到全局对象。在严格模式下调用函数则不影响默认绑定。

2.2 隐式绑定

当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。对象属性引用链中只有上一层或者说最后一层在调用中起作用。

隐式丢失

被隐式绑定的函数特定情况下会丢失绑定对象,应用默认绑定,把this绑定到全局对象或者undefined上。

参数传递就是一种隐式赋值,传入函数时也会被隐式赋值。回调函数丢失this绑定是非常常见的。

2.3 显式绑定

通过call(..) 或者 apply(..)方法。第一个参数是一个对象,在调用函数时将这个对象绑定到this。因为直接指定this的绑定对象,称之为显示绑定。

显示绑定无法解决丢失绑定问题。

解决方案:

  • 1、硬绑定

创建函数bar(),并在它的内部手动调用foo.call(obj),强制把foo的this绑定到了obj。这种方式让我想起了借用构造函数继承,没看过的可以点击查看 JavaScript常用八种继承方案

典型应用场景是创建一个包裹函数,负责接收参数并返回值。

创建一个可以重复使用的辅助函数。

ES5内置了Function.prototype.bind,bind会返回一个硬绑定的新函数,用法如下。

  • 2、API调用的“上下文”

JS许多内置函数提供了一个可选参数,被称之为“上下文”(context),其作用和bind(..)一样,确保回调函数使用指定的this。这些函数实际上通过call(..)apply(..)实现了显式绑定。

2.4 new绑定

  • 在JS中,构造函数只是使用new操作符时被调用的普通函数,他们不属于某个类,也不会实例化一个类。

  • 包括内置对象函数(比如Number(..))在内的所有函数都可以用new来调用,这种函数调用被称为构造函数调用。

  • 实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用”。

使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  • 1、创建(或者说构造)一个新对象。

  • 2、这个新对象会被执行[[Prototype]]连接。

  • 3、这个新对象会绑定到函数调用的this

  • 4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

使用new来调用foo(..)时,会构造一个新对象并把它(bar)绑定到foo(..)调用中的this。

手写一个new实现

使用这个手写的new

代码原理解析:

  • 1、用new Object()的方式新建了一个对象obj

  • 2、取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以 arguments会被去除第一个参数

  • 3、将 obj的原型指向构造函数,这样obj就可以访问到构造函数原型中的属性

  • 4、使用apply,改变构造函数this 的指向到新建的对象,这样 obj就可以访问到构造函数中的属性

  • 5、返回 obj

#3 优先级

new中使用硬绑定函数的目的是预先设置函数的一些参数,这样在使用new进行初始化时就可以只传入其余的参数(柯里化)。

4 绑定例外

4.1 被忽略的this

null或者undefined作为this的绑定对象传入callapply或者bind,这些值在调用时会被忽略,实际应用的是默认规则。

下面两种情况下会传入null

  • 使用apply(..)来“展开”一个数组,并当作参数传入一个函数

  • bind(..)可以对参数进行柯里化(预先设置一些参数)

总是传入null来忽略this绑定可能产生一些副作用。如果某个函数确实使用了this,那默认绑定规则会把this绑定到全局对象中。

更安全的this

安全的做法就是传入一个特殊的对象(空对象),把this绑定到这个对象不会对你的程序产生任何副作用。

JS中创建一个空对象最简单的方法是**Object.create(null)**,这个和{}很像,但是并不会创建Object.prototype这个委托,所以比{}更空。

4.2 间接引用

间接引用下,调用这个函数会应用默认绑定规则。间接引用最容易在赋值时发生。

4.3 软绑定

  • 硬绑定可以把this强制绑定到指定的对象(new除外),防止函数调用应用默认绑定规则。但是会降低函数的灵活性,使用硬绑定之后就无法使用隐式绑定或者显式绑定来修改this。

  • 如果给默认绑定指定一个全局对象和undefined以外的值,那就可以实现和硬绑定相同的效果,同时保留隐式绑定或者显示绑定修改this的能力。

使用:软绑定版本的foo()可以手动将this绑定到obj2或者obj3上,但如果应用默认绑定,则会将this绑定到obj。

5 this词法

ES6新增一种特殊函数类型:箭头函数,箭头函数无法使用上述四条规则,而是根据外层(函数或者全局)作用域(词法作用域)来决定this。

  • foo()内部创建的箭头函数会捕获调用时foo()的this。由于foo()的this绑定到obj1bar(引用箭头函数)的this也会绑定到obj1,箭头函数的绑定无法被修改(new也不行)。

ES6之前和箭头函数类似的模式,采用的是词法作用域取代了传统的this机制。

代码风格统一问题:如果既有this风格的代码,还会使用 seft = this 或者箭头函数来否定this机制。

  • 只使用词法作用域并完全抛弃错误this风格的代码;

  • 完全采用this风格,在必要时使用bind(..),尽量避免使用 self = this 和箭头函数。

本期思考题

依次给出console.log输出的数值。

公众号回复关键词“解析”获取本期答案

this指向undefined uiapp_JavaScript深入之史上最全5种this绑定全面解析相关推荐

  1. 【进阶3-1期】JavaScript深入之史上最全--5种this绑定全面解析

    this的绑定规则总共有下面5种. 1.默认绑定(严格/非严格模式) 2.隐式绑定 3.显式绑定 4.new绑定 5.箭头函数绑定 1 调用位置 调用位置就是函数在代码中被调用的位置(而不是声明的位置 ...

  2. 计算机集成电板 ppt,史上最全,PCB板和集成电路解析(干货分享)

    原标题:史上最全,PCB板和集成电路解析(干货分享) 目前的电路板,主要由以下组成: 线路与图面(Pattern):线路是做为原件之间导通的工具,在设计上会另外设计大铜面作为接地及电源层.线路与图面是 ...

  3. 史上最全的vue.js源码解析(四)

    虽然vue3已经出来很久了,但我觉得vue.js的源码还是非常值得去学习一下.vue.js里面封装的很多工具类在我们平时工作项目中也会经常用到.所以我近期会对vue.js的源码进行解读,分享值得去学习 ...

  4. java2019 数据结构算法面试题_GitHub - sjyw/java-interview: 史上最全Java面试题汇总与解析(505道):2019最新版...

    Java 面试全解析 知识树 课程亮点 500道 Java 常见面试题 + 14万字核心知识解析 丰富的 Java 技术栈:基础和框架,线程池和锁优化,SpringBoot 和分布式消息队列,数据结构 ...

  5. 微信小程序—史上最全78种炫到爆的自定义动画

    摘要 最近在研究小程序,搜集整理而来共计78种自定义动画,现分享给大家,并且写成demo,读者可通过体验获取想要的效果,复制粘贴使用,希望能共同学习. 部分效果图 体验途径 依次点击:custom系列 ...

  6. 史上最全| 14种自动化分拣系统合集

    导语 大家好,我是智能仓储物流技术研习社的社长,你的老朋友,老K. 新书上市<智能物流系统构成与技术实践> 2023年度-厂商宣传合作位--->点击详情 本文为研习社原创,违规转载必 ...

  7. 史上最全| 14种自动化分拣系统合集|拿走!

    导语 大家好,我是智能仓储物流技术研习社的社长,老K.今天给大家整理了14种不同种类的自动化分拣方式,供大家参考. 01移栽式 02偏转轮式 03扫臂式 04滑靴式 05侧向翻转 06推盘式 07交叉 ...

  8. 史上最全大数据实践应用案例解析

    目前最热门,最有发展前景的当属金融和IT行业了,而这两个行业的蓬勃发展自然离不开大数据.在金融领域中银行和保险业尤其适用于大数据技术,现在汇丰银行,英杰华等众多公司已通过分析海量数据大受裨益.举个例子 ...

  9. 这可能是史上最全的Python算法集!

    来源 | CSDN(ID:CSDNnews ) 本文是一些机器人算法(特别是自动导航算法)的Python代码合集. 其主要特点有以下三点:选择了在实践中广泛应用的算法:依赖最少:容易阅读,容易理解每个 ...

最新文章

  1. JS实现HTML上用button打开文件对话框
  2. 为什么不让安装卫xing×××啊
  3. Fixed: MacOS Mojave(10.14) 解决终端用Crontab报权限问题(不管是Root还是普通用户)及Linux基础(shell)...
  4. java 线程栈空间_java线程的内存不包含在JVM堆与栈中
  5. 什么是服务的幂等?为什么要实现幂等?
  6. node.js——sequelize-auto模块生成数据库models及使用
  7. PHP中如何防止直接访问或查看或下载config.php文件
  8. 已解决:mysql: [Warning] Using a password on the command line interface can be insecure.
  9. [转载]未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。
  10. 利用函数指针实现累加
  11. 【Advanced控制理论】Robust Control鲁棒控制(附Simulink程序)
  12. php12生肖是哪个,生肖查询-十二属相年份查询-生肖五行查询-12生肖顺序查询
  13. 神器推荐:应用之星,零代码就能制作炫酷的H5页面
  14. 选择system bus还是session bus?
  15. 【JAVAFX UI欣赏 之 滑条频谱】
  16. 泛函分析之集合的映射和可数集与不可数集
  17. win10同时安装wps和office时,如何设置默认应用为office!!!
  18. mysql 1032错误_如何快速解决MySQL 1032 主从错误
  19. 计算机无法打开这个应用,win10照片应用打不开提示“无法打开这应用”如何解决...
  20. msapro-note

热门文章

  1. 栈与队列1——设计getMin功能的栈
  2. windows10+Python3-如何安装numpy和matplotlib包
  3. mysql 允许远程登录
  4. 超好用的Swift 4.0 字符截取快速便捷方法
  5. [分享] 从定制Win7母盘到封装详细教程 By BILL ( 10月23日补充说明 )
  6. python windows错误码
  7. 软件外包是中国程序员的大金矿,大家一起来挣×××吧
  8. php 爬虫_Scrapy 爬虫完整案例-基础篇
  9. 网上的python教程值不值得买_Python新人入手线程技术教程,值得收藏
  10. linux fio释放内存,linux使用FIO测试磁盘的iops