js的this绑定规则以及箭头函数

目录

  • 调用位置
  • 默认绑定
  • 隐式绑定
    • 隐式丢失
  • 显式绑定
    • call
    • apply
    • bind
  • new绑定
  • 装箱
  • 绑定优先级
  • this规则之外
    • 忽略显式绑定
    • 间接函数引用
  • 箭头函数

调用位置

从字面意思上来理解,this似乎是指向自己的
然而在JavaScript中,this并不是绑定到自身
可以看这一个例子

        function foo(num) {console.log("num:" + num)this.count++}foo.count = 0for (var i = 0; i < 10; i++) {if (i > 5) {foo(i)}}console.log(foo.count)

结果
结果

显然从字面意思来理解this指向自身是错误的认知
事实上this并不是编写时绑定的,而是运行时绑定
我们判断this会绑定到什么首先就要分析它的调用位置

        function foo() {bar()//此时的调用栈为:全局--》foo--》barfunction bar() {baz()//此时的调用栈为:全局--》foo--》bar--》bazfunction baz() {}}}foo()//此时的调用栈为:全局--》foo

在寻找到它的调用位置之后我们就需要判断这里的this适用于以下四条规则中的哪一条

默认绑定

独立调用函数时适用此条,也可以看成当其他三条规则都不适用时适用这条规则
独立函数调用可以看成函数没有被绑定到某个对象上进行调用
例如下面这个例子

        function foo() {console.log(this)}foo()

结果
结果

此时的this绑定了全局对象window
值得注意的是,在严格模式下,这里的this会绑定到undefined

隐式绑定

另一种比较常见的绑定方式为通过某个对象调用

        function foo() {console.log(this)}var obj = {name: "obj",foo: foo}obj.foo()

结果
结果
此时的this绑定到了obj对象上了

隐式丢失

被隐式绑定的this有时也会应用默认绑定规则
例如下面这段代码

        function foo() {console.log(this)}var obj = {name: "obj",foo: foo}var bar = obj.foobar()

结果
可以看到this绑定到了window上,这就是隐式丢失

显式绑定

在上面的代码中我们可以看到隐式绑定也会有可能出现隐式丢失的现象,为了确保我们的this能正确的绑定到我们想要的对象上可以使用显式绑定
显式绑定可以通过传递参数的形式来把this绑定到参数
显示绑定有具体三种方式

call

call方法需要传入一个参数来作为this的绑定对象,如果函数需要参数则在后面用逗号隔开

        function foo(name, age) {console.log(this)console.log(name + " " + age)}var obj = {name: "obj",}foo.call(obj, "张三", 18)

结果
结果
这里可以看到this绑定到了obj上了
注意:call方法是立即执行

apply

apply方式与call方法相似,但传递参数的方式不同

        function foo(name, age) {console.log(this)console.log(name + " " + age)}var obj = {name: "obj",}foo.apply(obj, ["张三", 18])

结果
结果
这里可以看到this绑定到了obj上了
注意:apply方法也是立即执行的

bind

无论是apply绑定或者是call绑定,都不能完全解决this绑定丢失问题
当将函数作为参数传递给其他函数之后,很难知道其他函数会怎么调用这个函数
函数的this指向此时也不受你控制
为了解决这个问题,我们可以使用bind方法

        function foo() {console.log(this)}function bar(fn) {fn.call(obj)}var obj = {name: "obj",}bar(foo.bind(window))

结果
结果
bind方法不会立即执行函数,而是会返回一个新函数
新函数的this将会指向你所指定的对象
以后this的指向也始终会是预期

new绑定

当我们使用new关键字时,会执行以下几件事情

  1. 创建一个空对象
  2. 将_空对象_的this绑定到这个空对象
  3. 执行函数体里的代码
        function foo() {console.log(this)this.a = 2}var obj = {name: "obj",}var bar = new foo()console.log(bar.a)

结果
结果

可以看到此时的this已经绑定到了foo

装箱

无论是call还是apply还是bind,当我们传入一个原始值(如数字字符串)时会发生什么呢

        function foo() {console.log(this)this.a = 2}var obj = {name: "obj",}foo.call(123)foo.apply("123")

结果
结果
得到的结论就是如果你传入了一个原始值来当作this的绑定对象,这个原始值会被转换成它的对象形式
new Number()new String()等等
这通常被称为装箱

绑定优先级

当一个函数涉及了多条规则,规则与规则之间则会按照自己的优先级生效

  1. 毋庸置疑的是默认绑定优先级最低,是其他规则都不适用情况下的兜底条款

  2. 显示绑定优先级高于隐式绑定

        function foo() {console.log(this.name)this.a = 2}var obj = {name: "obj",foo: foo}var obj2 = {name: "obj2",foo: foo}obj.foo.call(obj2)
    

    结果
    结果

  3. new绑定比隐式绑定优先级高

        function foo() {this.a = 2}var obj = {name: "obj",a: 4,foo: foo}var obj2 = new obj.foo()console.log(obj2.a)
    

    结果
    结果

  4. new绑定无法与call/apply方法一起使用,但我们可以通过与bind方法比较来得到结果

        function foo() {console.log(this)}var obj = {name: "obj",}var obj2 = foo.bind(obj)new obj2
    

    结果
    结果
    我们可以知道new绑定优先级高于显式绑定

this规则之外

在现实使用中,我们总有些语法超出了规则之外

忽略显式绑定

当传入的参数是null或者为undefined时,这个显式绑定忽略,使用默认绑定

        function foo() {console.log(this)}foo.call(null)foo.call(undefined)

结果
结果

间接函数引用

创建一个函数的间接引用,这种情况适用默认规则

        function foo() {console.log(this)}var obj = {foo: foo}var obj2 = {name: "obj2"};(obj2.foo = obj.foo)()

结果
结果

箭头函数

ES6中提出了一种新函数,他的名字叫箭头函数
箭头函数中,其实并没有this
所以并不适用上面提到的四条规则
箭头函数中的this是由其外部作用域来决定的
当箭头函数中遇到this时,箭头函数便会去它的外层作用域寻找

        var obj = {bar: function () {var foo = () => {console.log(this)}return foo}}var baz = obj.bar()baz()

结果
结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/27842.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经典常谈思维导图怎么制作?手把手教你制作

经典常谈思维导图怎么制作&#xff1f;创建思维导图可以帮助我们更好地组织和整理信息&#xff0c;帮助我们更好地理解和记忆信息。它可以使我们更高效地学习和工作&#xff0c;并帮助我们更好地表达和分享我们的想法和想法。因此&#xff0c;制作思维导图是一种非常有用的技能…

适合投资者的交易策略,4步找到

在外汇交易市场中&#xff0c;根据市场情况和个人投资目标&#xff0c;制定灵活的交易策略是至关重要的。Forexclub认为投资者可以通过结合多种交易策略&#xff0c;打造出全面、科学且适合自己的外汇交易策略。 首先&#xff0c;基于技术指标的交易策略是判断市场趋势和转折点…

剑指 Offer 29. 顺时针打印矩阵

输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输入&#xff1a;matrix [[1,2,3,4],[5,6,7,8],[9,10,11,12]] …

【深度学习】张量的广播专题

一、说明 张量广播&#xff08;tensor broadcasting&#xff09;是一种将低维张量自动转化为高维张量的技术&#xff0c;使得张量之间可以进行基于元素的运算&#xff08;如加、减、乘等&#xff09;。在进行张量广播时&#xff0c;会将维度数较少的张量沿着长度为1的轴进行复制…

【深度学习】了解残差网 ResNet 和 ResNeXt 的架构

一、说明 了解和实现 ResNet 和 ResNeXt 的架构以实现最先进的图像分类&#xff1a;从Microsoft到 Facebook [第 1 部分]&#xff0c;在这篇由两部分组成的博客文章中&#xff0c;我们将探讨残差网络。更具体地说&#xff0c;我们将讨论Microsoft研究和Facebook AI研究发布的三…

【C++初阶】list的模拟实现 附源码

一.list介绍 list底层是一个双向带头循环链表&#xff0c;这个我们以前用C语言模拟实现过&#xff0c;->双向带头循环链表 下面是list的文档介绍&#xff1a; list文档介绍 我们会根据 list 的文档来模拟实现 list 的增删查改及其它接口。 二.list模拟实现思路 既然是用C模拟…

【Vue】给 elementUI 中的 this.$confirm、this.$alert、 this.$prompt添加按钮的加载效果

文章目录 主要使用 beforeClose 方法实现 loading 的效果beforeClose MessageBox 关闭前的回调&#xff0c;会暂停实例的关闭 function(action, instance, done)1. action 的值为confirm, cancel或close。 2. instance 为 MessageBox 实例&#xff0c;可以通过它访问实例上的属…

Django + Bootstrap - 【echart】 统计图表进阶使用-统计用户日活日增、月活月增等数据(二)

一. 前言 Bootstrap是一个流行的前端框架&#xff0c;而ECharts是一个流行的可视化库。 Bootstrap可以用来设计网站和应用程序的用户界面&#xff0c;而ECharts可以用来创建交互式和可视化的图表。 chart.js中文文档&#xff1a;http://www.bootcss.com/p/chart.js/docs/ 二. …

LT8619B 是一款HDMI转TTL或者2 PORT LVDS的芯片。

LT8619B 1. 概述 LT8619B是龙迅基于清除边缘技术的高性能HDMI接收芯片&#xff0c;符合HDMI 1.4&#xff08;高清多媒体接口&#xff09;规范。RGB 输出端口可支持 RGB888/RGB666/RGB565 格式&#xff0c;输出分辨率最高可支持 4Kx2K 分辨率。凭借可编程标量&#xff0c;LT86…

切换.net Framework 版本后,出现NuGet 包是使用不同于当前目标框架的目标框架安装的,可能需要重新安装

问题现象&#xff1a; 由于添加新的dll文件&#xff0c;依赖的.NET Framework版本与当前的不一致&#xff0c;在vs 中切换了目标框架版本后&#xff0c;运行程序&#xff0c;出现以下的warnning信息&#xff1a; 一些 NuGet 包是使用不同于当前目标框架的目标框架安装的&#…

控制对文件访问

控制对文件访问 Linux文件权限 权限文件影响目录影响r读取文件内容列出目录内容w更改文件内容创建删除目录文件x作为命令执行目录可以变成当前工作目录 命令行管理文件系统权限 更改文件和目录权限 chmod chmod WhoWhatWhich file|directoryWho (u,g,o,a代表用户&#xff…

分布式事务 Seata

分布式事务 Seata 事务介绍分布式理论Seata 介绍Seata 部署与集成Seata TC Server 部署微服务集成 Seata XA 模式AT 模式AT 模式执行过程读写隔离写隔离读隔离 实现 AT 模式 TCC 模式TCC 模式介绍实现 TCC 模式 Saga 模式Seata 四种模式对比 事务介绍 事务&#xff08;Transac…