深度解析javascript中的this(二)

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: 深度解析javascript中的this(二)

前言

       上篇文章我们初步了解了有关this的知识,在不考虑箭头函数的情况下,this指向函数的调用者,这一章我们将进一步学习了解this

正文

调用位置

       在理解 this 的绑定过程之前,首先要理解调用位置:调用位置就是函数在代码中被调用的位置(而不是声明的位置)。最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数)。比如看下面的例子:

640.png

绑定规则

       对于this,其实并不简单是针对调用者,它还有更细致的绑定规则,分为四种情况,下面我们会就这四种情况做一个细致的分析


默认绑定

       首先要介绍的是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。

       这里按照我们上一章的解释,因为foo可以视为window.foo,所以this指向也会指向window,但是更准确地说,其实这里应用的是默认绑定的规则,所以this指向全局对象。但是如果使用严格模式(strict mode),那么全局对象将无法使用默认绑定,因此 this 会绑定到 undefined

640.png

隐式绑定

       另一条需要考虑的规则是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含,其实还是我们上一章说到的规则,在不考虑箭头函数的情况,this指向它外层函数的调用者,我们来看一个简单的例子:

640.png

把注意力集中在foo函数本身的调用者就可以,也就是obj2,至于别的不用在意只是干扰项而已

隐式丢失

       一个最常见的 this 绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说它会应用默认绑定,从而把 this 绑定到全局对象或者 undefined 上,取决于是否是严格模式。比如下面的例子:

640.png

       这里本来直接执行obj.foo应该是返回2的,但是虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是 foo 函数本身,因此此时的bar() 其实是一个不带任何修饰的函数调用,因此应用了默认绑定。也就是隐式丢失的现象

       一种更微妙、更常见并且更出乎意料的情况发生在传入回调函数时:

640.png

       参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值,所以结果和上一个例子一样。

       所以请记住,对隐式绑定的函数如果进行了间接调用,便会出现隐式丢失的问题,将自动采用默认绑定


显式绑定

       那么如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该怎么做呢?。具体点说,可以使用函数的 call(…) 和apply(…) 方法。大家应该对这两个方法已经很熟悉了,用这个两个方法就可以实现在某个对象上强制调用函数。上一小结我们提到的隐式丢失问题,我们就可以尝试用显式绑定来解决

硬绑定

640.png

       我们来看看这个变种到底是怎样工作的。我们创建了函数 bar(),并在它的内部手动调用了 foo.call(obj),因此强制把 foo 的 this 绑定到了 obj。无论之后如何调用函数 bar,它总会手动在 obj 上调用 foo。这种绑定是一种显式的强制绑定,因此我们称之为硬绑定。

       由于硬绑定是一种非常常用的模式,所以在 ES5 中提供了内置的方法 Function.prototype.bind


API调用的“上下文”

       第三方库的许多函数,以及 JavaScript 语言和宿主环境中许多新的内置函数,都提供了一个可选的参数,通常被称为“上下文”(context),其作用和 bind(…) 一样,确保你的回调函数使用指定的 this。


new绑定

       new绑定是this的最后一条绑定规则,在传统的面向类的语言中,“构造函数”是类中的一些特殊方法,使用 new 初始化类时会调用类中的构造函数。JavaScript 也有一个 new 操作符,使用方法看起来也和那些面向类的语言一样,绝大多数开发者都认为 JavaScript 中 new 的机制也和那些语言一样。然而,JavaScript 中 new 的机制实际上和面向类的语言完全不同。

       javascript中有一个重要但是非常细微的区别:实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用”。

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

  1. 创建(或者说构造)一个全新的对象。
  2. 这个新对象会被执行 [[ 原型 ]] 连接。
  3. 这个新对象会绑定到函数调用的 this。
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

小结

       这一章我们主要讲了javascript中的this绑定的四个规则,默认绑定,隐式绑定,显式绑定和new绑定,同学们可能会有一点疑惑,如果同时有这几种绑定,他们之间互相冲突应该怎么办,因为篇幅有限,我将在下一章给大家介绍这四种规则的优先级以及造成这种优先级的源码原因,谢谢学习

目录
相关文章
|
3月前
|
JavaScript 前端开发 开发者
Nest.js控制器深度解析:路由与请求处理的高级特性
以上就是对 NestJS 控制层高级特性深度解析:从基本概念到异步支持再到更复杂场景下拦截其与管道等功能性组件运用都有所涉及,希望能够帮助开发者更好地理解和运用 NestJS 进行高效开发工作。
347 15
|
3月前
|
JavaScript 前端开发 IDE
TypeScript vs. JavaScript:技术对比与核心差异解析
TypeScript 作为 JavaScript 的超集,通过静态类型系统、编译时错误检测和强大的工具链支持,显著提升代码质量与可维护性,尤其适用于中大型项目和团队协作。相较之下,JavaScript 更灵活,适合快速原型开发。本文从类型系统、错误检测、工具支持等多维度对比两者差异,并提供技术选型建议,助力开发者合理选择。
687 1
|
3月前
|
存储 JavaScript 前端开发
JavaScript 语法全面解析
JavaScript 语法体系丰富且不断更新,从基础的变量声明、数据类型,到复杂的函数、对象、异步语法,每个知识点都需要开发者深入理解并灵活运用。本文梳理的 JS 语法核心内容,可为开发者提供系统的学习框架,后续还需通过大量实践(如编写交互组件、实现业务逻辑)巩固知识,逐步提升 JS 编程能力,应对前端开发中的各类挑战。
|
6月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
276 19
|
7月前
|
JSON 前端开发 Serverless
Mock.js 语法结构全解析
Mock.js 的语法规范介绍,从数据模板定义规范和数据占位符定义规范俩部分介绍, 让你更好的使用 Mock.js 来模拟数据并提高开发效率。
|
9月前
|
数据采集 前端开发 JavaScript
金融数据分析:解析JavaScript渲染的隐藏表格
本文详解了如何使用Python与Selenium结合代理IP技术,从金融网站(如东方财富网)抓取由JavaScript渲染的隐藏表格数据。内容涵盖环境搭建、代理配置、模拟用户行为、数据解析与分析等关键步骤。通过设置Cookie和User-Agent,突破反爬机制;借助Selenium等待页面渲染,精准定位动态数据。同时,提供了常见错误解决方案及延伸练习,帮助读者掌握金融数据采集的核心技能,为投资决策提供支持。注意规避动态加载、代理验证及元素定位等潜在陷阱,确保数据抓取高效稳定。
285 17
|
9月前
|
存储 JavaScript 前端开发
全网最全情景,深入浅出解析JavaScript数组去重:数值与引用类型的全面攻略
如果是基础类型数组,优先选择 Set。 对于引用类型数组,根据需求选择 Map 或 JSON.stringify()。 其余情况根据实际需求进行混合调用,就能更好的实现数组去重。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
消息中间件 JavaScript 前端开发
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
|
前端开发 JavaScript
web前端-JavaScript中的call、apply和bind方法(改变this指向)
文章目录 每日推荐 正文开始 call()和apply() bind()() call、apply和bind方法的区别 相同点 不同点 this指向的四种情况总结
web前端-JavaScript中的call、apply和bind方法(改变this指向)
|
自然语言处理 JavaScript 前端开发
不必硬背,彻底理解JavaScript中的this指向!(上)
1. 执行上下文 提到 this,还得从执行上下文说起。在执行上下文中,包含了变量环境、词法环境、外部环境、this:
438 0

推荐镜像

更多
  • DNS