美文网首页
一文了解 this

一文了解 this

作者: vavid | 来源:发表于2021-01-25 16:16 被阅读0次

思考题: 以下这段代码打印输出是什么?

let bar = { 
  myName: "www.cctalk.com", 
  printName: function () { 
    console.log(myName) 
  } 
}
function foo() { 
  let myName = "沪江教育" 
  return bar.printName 
}
let myName = "享互"
let _printName = foo()
_printName()
bar.printName()

this 介绍:
this 是和执行上下文绑定的,执行上下文主要分为三种——全局执行上下文、函数执行上下文和 eval 执行上下文,所以对应的 this 也只有这三种——全局执行上下文中的 this、函数中的 this 和 eval 中的 this。
由于eval 执行上下文使用不多,故先了解:全局执行上下文中的 this、函数中的 this:

一、 全局执行上下文中的 this:
全局执行上下文中的 this 是指向 window 对象的。
可以在全局环境下使用 console.log(this) 进行验证,确认 this 是否打印输出 window 对象

二、 函数中的 this

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

在 foo 函数内部打印出来 this 值,执行这段代码,打印出来的也是 window 对象,
这说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。
那能不能设置执行上下文中的 this 来指向其他对象呢?
答案是肯定的。通常情况下,有下面三种方式来设置函数执行上下文中的 this 值。

  1. 通过函数的 call 方法设置, 其实除了 call 方法,你还可以使用 bind 和 apply 方法来设置函数执行上下文中的 this
let bar11 = {
  myName : "享互",
  test1 : 1
}
function foo11(){
  this.myName = "沪江"
}
foo11.call(bar11) 
console.log(bar11)    // bar11 = { myName: '沪江', test1: 1 }
console.log(myName)   // undefined
  1. 通过对象调用方法设置
    使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的。
let myObj = {
  name : "沪江", 
  showThis: function(){
    console.log(this)
  }
}
myObj.showThis()

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

稍微改变下调用方式,把 showThis 赋给一个全局对象,然后再调用该对象,代码如下所示:

let myObj111 = {
  name : "极客时间",
  showThis: function(){
    this.name = "极客邦"
    console.log(this)
  }
}
let foo111 = myObj111.showThis
foo111()

结论:
通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。 在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。

  1. 通过构造函数中设置
function CreateObject(){
  this.name = "极客时间"
}
let myObject = new CreateObject()

其实,当执行 new CreateObject() 的时候,JavaScript 引擎做了如下四件事:
1、首先创建了一个空对象 tempObj;
2、接着调用 CreateObject.call 方法,并将 tempObj 作为 call 方法的参数,这样当 CreateObject 的执行上下文创建时,它的 this 就指向了 tempObj 对象;
3、然后执行 CreateObject 函数,此时的 CreateObject 函数执行上下文中的 this 指向了 tempObj 对象;
4、最后返回 tempObj 对象。

let myObject1 = (function () {
  let tempObj = {}
  CreateObject.call(tempObj)
  return tempObj
})()

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

一、嵌套函数中的 this 不会从外层函数中继承
函数 bar 中的 this 指向的是全局 window 对象,而函数 showThis 中的 this 指向的是 myObj1111 对象。

let myObj2 = {
  name : "沪江", 
  showThis: function(){
    console.log(this)
    function bar(){
      console.log(this)
    }
    bar()
  }
}
myObj2.showThis()

解决方法:1、声明一个变量 self 用来保存 this
这个方法的的本质是把 this 体系转换为了作用域的体系。

let myObj3 = {
  name : "沪江", 
  showThis: function(){
    console.log(this)
    var self = this
    function bar(){
      self.name = "享互"
    }
    bar()
  }
}
myObj3.showThis()
console.log(myObj3.name)
console.log(window.name)

解决方法:2、使用 ES6 中的箭头函数来解决这个问题
因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。

let myObj4 = {
  name : "极客时间", 
  showThis: function(){
    console.log(this)
    var bar = ()=>{
      this.name = "极客邦"
      console.log(this)
    }
    bar()
  }
}
myObj4.showThis()
console.log(myObj4.name)
console.log(window.name)

二、普通函数中的 this 默认指向全局对象 window
在默认情况下调用一个函数,其执行上下文中的 this 是默认指向全局对象 window 的。
不过这个设计也是一种缺陷,因为在实际工作中,我们并不希望函数执行上下文中的 this 默认指向全局对象,因为这样会打破数据的边界,造成一些误操作。
如果要让函数执行上下文中的 this 指向某个对象,最好的方式是通过 call 方法来显示调用。
这个问题可以通过设置 JavaScript 的“严格模式”来解决。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined,这就解决上面的问题了。

总结
首先,在使用 this 时,为了避坑,要谨记以下三点:
1、当函数作为对象的方法调用时,函数中的 this 就是该对象;
2、当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;
3、嵌套函数中的 this 不会继承外层函数的 this 值。

https://juejin.cn/post/6844903573428371464

相关文章

  • 2021备考:一文带你全面了解MPA

    2021考研,洪桥教育推出【一文带你全面了解】系列, 备考的入门信息,让你一文搞定 MBA专栏|一文带你全面了解M...

  • 一文了解 this

    思考题: 以下这段代码打印输出是什么? this 介绍:this 是和执行上下文绑定的,执行上下文主要分为三种——...

  • 一文理解51%攻击和区块链分叉

    系列文章 一文近距离了解区块链一文深入理解区块链挖矿机制

  • 一文了解宫崎骏

    据说,宫崎骏又复出了O(∩_∩)O哈哈哈~ 宫老爷子大家都很熟悉,下面就简单介绍一下好拉。 宫崎骏,1941年1月...

  • 一文了解宫崎骏

    据说,宫崎骏又复出了O(∩_∩)O哈哈哈~ 宫老爷子大家都很熟悉,下面就简单介绍一下好拉。 宫崎骏,1941年1月...

  • webpack一文了解

    快速的带各位同学入门这款自动化工具,看完之后你就懂了,你就真的懂了 一定要看看我粘贴的代码,注释都在里面写着呢,如...

  • 一文了解Zookeeper

    Zookeeper是Apache开源的一个分布式框架,它主要为分布式应用提供协调服务。 Zookeeper主要负责...

  • 一文了解JVM

    一、什么是JVM JVM是Java Virtual Machine(Java 虚拟机)的缩写,JVM是一种用于计算...

  • 一文了解Zcoin

    引言 这一段时间,金马在超级会员群里开展了一个TOP100活动,即每周由一名超级会员介绍一个市值位于前100名的数...

  • 一文了解Docker

    本文转自杨奇龙老师的公众号(yangyidba),他长期关注于数据库技术以及性能优化,故障案例分析,数据库运维技术...

网友评论

      本文标题:一文了解 this

      本文链接:https://www.haomeiwen.com/subject/wnhizktx.html