JS —— (14)一文搞定 this 指向【含有.apply、.call、.bind()】

一. this 的五种绑定形式

常见的 this绑定 有五种形式:默认绑定隐式绑定显式绑定new绑定箭头函数绑定

<1> 默认绑定

默认绑定 可以理解为函数调用时无任何调用前缀的情景 ,默认绑定时this指向全局对象 (非严格模式)

注意:

  • 在严格模式下,默认的 this 绑定指向 undefined
  • 但如果是在非严格模式下调用不在严格模式下的函数,并不会影响 this 指向!!!
<2> 隐式绑定
(1)

隐式绑定,可以理解为函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上。且如果函数调用前存在多个对象,this指向距离调用自己最近的对象。

  • 如上,输出的是 undefined ,因为 obj 对象中并没有 name 属性,它的原型链上也没有!!!
(2) 隐式丢失的情况:

隐式绑定丢失最常见的就是两种情况:作为参数传递和变量赋值

  • 作为参数传递

如上,传进去的只是一个函数,但该函数并没有与 obj 形成绑定关系,只是通过 obj 访问该函数,并把该函数作为参数传递了而已!!!

  • 变量赋值

如上,跟参数传递本质是一样的,只是把该函数赋值给了一个变量,并没有形成绑定关系!!

(3) 补充: 作用域链与原型链的关系:

  • 作用域链

    javascript 复制代码
     - 当访问一个变量时,解释器会先在当前作用域中查找标识符,如果没有找到的话就去父作用域
     中找,作用域链顶端是全局对象 window ,如果 window 对象上没有该属性,就会报错!!
  • 原型链

    javascript 复制代码
     - 当访问一个对象的某个属性时,首先会查找当前的对象,如果没有就顺着该对象的原型链
     找,原型链的顶端是 Object 对象的原型 ,也就是 null ,如果没有找到的话,会返回
     undefined,而不是报错!!!
<3> 显式绑定

(1)

显式绑定可以理解为通过call、apply以及bind方法改变this的行为。在js中,当我们调用一个函数时,我们习惯称之为函数调用,函数处于一个被动的状态;而call与apply让函数从被动变主动,函数能主动选择自己的上下文,所以这种写法我们又称之为函数应用

注意:

  • 如果在使用call之类的方法改变this指向时,指向参数提供的是null或者undefined,那么 this 将指向全局对象。

(2) 补充:call、apply、bind的区别:

  • .call、apply与bind都用于改变this绑定,但call、apply在改变this指向的同时还会执行函数 ,而bind在改变this后是返回一个全新的boundFunction绑定函数,这也是为什么上方例子中bind后还加了一对括号 ()的原因。

  • 【重点】 bind属于硬绑定返回的 boundFunction 的 this 指向无法再次通过bind、apply或 call 修改;call与apply的绑定只适用当前调用,调用完就没了,下次要用还得再次绑。

  • call与apply功能完全相同,唯一不同的是call方法传递函数调用形参是以散列形式 ,而apply方法的形参是一个数组。在传参的情况下,call的性能要高于apply,因为apply在执行时还要多一步解析数组。

<4> new 绑定

new绑定可以理解为使用构造函数 new 出来一个新的实例对象,构造函数体内的this将指向新对象echo上(可以抽象理解为新对象就是this)

<5> 箭头函数绑定【箭头函数的 this 绑定成功后也无法再通过三个方法修改,除了直接改变其所在作用域的 this 指向】

箭头函数内部是没有 this 的,箭头函数内部的 this 指向完全取决于外层作用域中的 this 指向。外层作用域或函数的this指向谁,箭头函数中的this便指向谁。如果外层作用域是 window ,那箭头函数内部的 this 就指向全局对象 window。

如上,bar 指向 fn 函数执行完后返回的箭头函数,而执行 bar ,就是执行返回的箭头函数。因为该箭头函数外部作用域的函数 fn 的作用域,而该作用域中的 this 指向 onj1 ,因为函数 fn 通过 .call显式绑定与 obj1 相绑定了!!

注意:

  • 箭头函数this还有一个特性,那就是一旦箭头函数的this绑定成功,也无法被再次修改,有点硬绑定的意思。但是我们还是可以通过修改外层函数this指向达到间接修改箭头函数this的目的。
<6> this 绑定的优先级
  • 显式绑定 > 隐式绑定 > 默认绑定

  • new 绑定 > 隐式绑定 > 默认绑定

因为 new绑定和显示绑定不会同时出现(同时出现会报错),就没有两者的比较

二. 关于 this 指向的经典面试题

[](js 从两道面试题加深理解闭包与箭头函数中的this - 听风是风 - 博客园)

相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
LCG元3 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
迷雾漫步者3 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript