浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this

简介: 浏览器原理 10 # this:从 JavaScript 执行上下文的视角讲清楚 this

说明

浏览器工作原理与实践专栏学习笔记



为什么需要 this


对象内部的方法中使用对象内部的属性是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,基于这个需求,JavaScript 又搞出来另外一套 this 机制


作用域链和 this 是两套不同的系统,它们之间基本没太多联系。



JavaScript 中的 this 是什么


执行上下文中的 this:this 是和执行上下文绑定的,每个执行上下文中都有一个 this。

20210408100039355.png

执行上下文主要分为三种,那么 this 也只有这三种


  1. 全局执行上下文----全局执行上下文中的 this
  2. 函数执行上下文----函数中的 this
  3. eval 执行上下文----eval 中的 this



全局执行上下文中的 this


全局执行上下文中的 this 是指向 window 对象的。


这也是 this 和作用域链的唯一交点,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象。


我们可以打开控制台输入 console.log(this)

20210408102313184.png


函数执行上下文中的 this

例子:

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



20210408111716790.png


打印出来发现还是指向 window 对象,说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。




改变 this 指向


设置函数执行上下文中的 this 值的三种方式


1. 通过函数的 call、bind 和 apply方法设置

以 call 为例:下面的 this 指向 obj 对象


let obj = {
  myName : "kaimo",
}
function foo(){
  this.myName = "凯小默"
}
foo.call(obj)
console.log(obj)
console.log(myName)

20210408113015641.png


2. 通过对象调用方法设置

例子:this 指向了 myObj

var myObj = {
  name : "凯小默", 
  showThis: function(){
    console.log(this)
  }
}
myObj.showThis()


可以认为 JavaScript 引擎在执行 myObject.showThis() 时,将其转化为了 myObj.showThis.call(myObj)


20210408113428677.png

使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的。


改造一下代码:this 又指向了 window 对象

var myObj = {
  name : "凯小默",
  showThis: function(){
    this.name = "kaimo"
    console.log(this)
  }
}
var foo = myObj.showThis
foo()


20210408115721779.png


在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。



3. 通过构造函数中设置

例子:

function CreateObj(){
  this.name = "凯小默"
}
var myObj = new CreateObj()


当执行 new CreateObj()的时候,JavaScript 引擎做了如下四件事:


   首先创建了一个空对象 tempObj

   调用 CreateObj.call 方法,并将 tempObj 作为 call 方法的参数,这样当 CreateObj 的执行上下文创建时,它的 this 就指向了 tempObj 对象

   执行 CreateObj 函数,此时的 CreateObj 函数执行上下文中的 this 指向了 tempObj 对象

   最后返回 tempObj 对象



大致就是:

var tempObj = {}
  CreateObj.call(tempObj)
  return tempObj


更多 new 的知识点可以查看【new 运算符】



this 的设计缺陷以及应对方案


1. 嵌套函数中的 this 不会从外层函数中继承


例子:

var myObj = {
  name : "凯小默", 
  showThis: function(){
    console.log(this)
    function bar(){console.log(this)}
    bar()
  }
}
myObj.showThis()

20210408144422156.png


解决方法一:声明一个变量用来保存 this,其本质就是把 this 体系转换为了作用域的体系

var self = this;
function bar(){ 
  self.name = "kaimo" 
}


解决方法二:使用 ES6 中的箭头函数来解决这个问题

因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。

var bar = ()=>{ 
  this.name = "kaimo" 
  console.log(this) 
}


2. 普通函数中的 this 默认指向全局对象 window

可以通过设置 JavaScript 的“严格模式”来解决。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined



注意点


   当函数作为对象的方法调用时,函数中的 this 就是该对象

   当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window

   嵌套函数中的 this 不会继承外层函数的 this 值

   箭头函数没有自己的执行上下文,所以箭头函数的 this 就是它外层函数的 this。





目录
相关文章
|
2月前
|
移动开发 JavaScript 前端开发
一些处理浏览器兼容性问题的JavaScript库
这些库在处理浏览器兼容性问题方面都有着各自的特点和优势,可以根据具体的需求和项目情况选择合适的库来使用,从而提高代码的兼容性和稳定性,为用户提供更好的体验。同时,随着浏览器技术的不断发展,还需要持续关注和学习新的兼容性解决方案。
112 48
|
2月前
|
JSON 移动开发 JavaScript
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
在浏览器执行js脚本的两种方式
|
2月前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
86 1
|
2月前
|
JavaScript 前端开发 数据处理
模板字符串和普通字符串在浏览器和 Node.js 中的性能表现是否一致?
综上所述,模板字符串和普通字符串在浏览器和 Node.js 中的性能表现既有相似之处,也有不同之处。在实际应用中,需要根据具体的场景和性能需求来选择使用哪种字符串处理方式,以达到最佳的性能和开发效率。
|
2月前
|
监控 JavaScript 算法
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
2月前
|
算法 开发者
Moment.js库是如何处理不同浏览器的时间戳格式差异的?
总的来说,Moment.js 通过一系列的技术手段和策略,有效地处理了不同浏览器的时间戳格式差异,为开发者提供了一个稳定、可靠且易于使用的时间处理工具。
52 1
|
3月前
|
存储 JavaScript 前端开发
深入理解 JavaScript 执行上下文与 this 绑定机制
JavaScript 代码执行时,会为每段可执行代码创建对应的执行上下文,其中包含三个重要属性:变量对象、作用域链、和 this。本文深入剖析了执行上下文的生命周期以及 this 在不同情况下的指向规则。通过解析全局上下文和函数上下文中的 this,我们详细讲解了 this 的运行期绑定特性,并展示了如何通过调用方式影响 this 的绑定对象。同时,文中对箭头函数 this 的特殊性以及四条判断 this 绑定的规则进行了总结,帮助开发者更清晰地理解 JavaScript 中的 this 行为。
96 8
深入理解 JavaScript 执行上下文与 this 绑定机制
|
2月前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
363 9
|
2月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
193 1
|
2月前
|
自然语言处理 JavaScript 前端开发
如何在 JavaScript 中创建执行上下文
在JavaScript中,每当执行一段代码时,都会创建一个执行上下文。它首先进行变量、函数声明的创建和内存分配(即变量环境和词法环境的建立),接着进入代码执行阶段,处理具体逻辑。