浏览器原理 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。





目录
相关文章
|
12天前
|
JavaScript 前端开发 Serverless
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
27 2
|
30天前
|
Web App开发 JavaScript 前端开发
浏览器与Node.js事件循环:异同点及工作原理
浏览器与Node.js事件循环:异同点及工作原理
|
30天前
|
前端开发 JavaScript Java
Java与JavaScript的区别与联系:有人的地方就有江湖,有浏览器的地方就有JavaScript
Java与JavaScript的区别与联系:有人的地方就有江湖,有浏览器的地方就有JavaScript
|
1天前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【6月更文挑战第15天】JavaScript的`this`根据调用方式变化:非严格模式下直接调用时指向全局对象(浏览器为window),严格模式下为undefined。作为对象方法时,`this`指对象本身。用`new`调用构造函数时,`this`指新实例。`call`,`apply`,`bind`可显式设定`this`值。箭头函数和绑定方法有助于管理复杂场景中的`this`行为。
9 3
|
1天前
|
JavaScript 前端开发
js怎样获取浏览器窗口尺寸
js怎样获取浏览器窗口尺寸
|
1天前
|
JavaScript 前端开发
JavaScript BOM 浏览器对象模型
JavaScript BOM 浏览器对象模型
|
10天前
|
缓存 自然语言处理 前端开发
深入剖析JavaScript引擎的工作原理
【6月更文挑战第3天】JavaScript引擎由解析器、解释器、优化器和垃圾回收器组成,它们协同完成代码的解析、编译和执行。解析器将源代码转为抽象语法树(AST),编译阶段进行作用域分析和变量提升。解释器执行AST,优化器在代码频繁执行时进行即时编译以提高性能。垃圾回收器自动回收不再使用的内存,防止泄漏。理解这些原理有助于优化代码和提升Web应用性能。
10 1
|
10天前
|
JavaScript 前端开发 网络协议
浏览器的工作原理
主要分为导航、获取数据、HTML解析、css解析、执行javaScript、渲染树几个步骤。
16 1
|
16天前
|
JavaScript 前端开发
js中改变this指向、动态指定函数 this 值的方法
js中改变this指向、动态指定函数 this 值的方法
|
29天前
|
前端开发 JavaScript
JavaScript:this-关键字,2024中级前端开发面试解答
JavaScript:this-关键字,2024中级前端开发面试解答