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 - 听风是风 - 博客园)

相关推荐
懒大王爱吃狼1 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨2 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
逐·風5 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫5 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦6 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子6 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山7 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享7 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄8 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
鱼跃鹰飞9 小时前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试