之前的文章《中秋技巧篇:如何用CSS实现地球和月亮的公转(收藏)》中,给大家介绍了如何用CSS实现地球和月亮的公转。下面本篇文章给大家了解js中this指向问题,有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助。

一文讲解js中this指向问题(附代码)插图

JS中this指向问题

相信我,只要记住本文的7步口诀,就能彻底掌握 JS 中的this指向。

先念口诀:箭头函数、new、bind、apply 和 call、欧比届点(obj.)、直接调用、不在函数里。

按照口诀的顺序,只要满足前面某个场景,就可以确定this指向了。

接下来按照口诀顺序对它们进行详解,文中示例代码都运行在ChromeConsole控制台中。

文末有精心准备的练习题,用于检验学习成果,别忘了试试~

1. 箭头函数

箭头函数排在第一个是因为它的this不会被改变,所以只要当前函数是箭头函数,那么就不用再看其他规则了。

箭头函数的this是在创建它时外层this的指向。这里的重点有两个:

1、创建箭头函数时,就已经确定了它的this指向。

2、箭头函数内的this指向外层的this

所以要知道箭头函数的this就得先知道外层this的指向,需要继续在外层应用七步口诀。

2. new

当使用 new 关键字调用函数时,函数中的 this 一定是 JS 创建的新对象。

读者可能会有疑问,“如果使用new关键调用箭头函数,是不是箭头函数的this就会被修改呢?”。

我们在控制台试一下。

func = () => {} 
new func() // throw error

微信截图_20210917095948.png

从控制台中可以看出,箭头函数不能当做构造函数,所以不能与new一起执行。

3. bind

多次 bind 时只认第一次 bind 的值

易错点

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

func.bind(1).bind(2)() // 1

箭头函数中 this 不会被修改

func = () => {
  // 这里 this 指向取决于外层 this,参考口诀 7 「不在函数里」
  console.log(this)
}

func.bind(1)() // Window,口诀 1 优先

bind 与 new

易错点

function func() {
  console.log(this, this.__proto__ === func.prototype)
}

boundFunc = func.bind(1)
new boundFunc() // Object true,口诀 2 优先

4. apply 和 call

apply()call()的第一个参数都是this,区别在于通过apply调用时实参是放到数组中的,而通过call调用时实参是逗号分隔的。

箭头函数中 this 不会被修改

易错点

func = () => {
  // 这里 this 指向取决于外层 this,参考口诀 7 「不在函数里」
  console.log(this)
}

func.apply(1) // Window,口诀 1 优先

bind 函数中 this 不会被修改

易错点

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

boundFunc = func.bind(1)
boundFunc.apply(2) // 1,口诀 3 优先

5. 欧比届点(obj.)

function func() {
  console.log(this.x)
}

obj = { x: 1 }
obj.func = func
obj.func() // 1

这里就不用代码例证箭头函数和 bind 函数的优先级更高了,有兴趣可自行尝试吧。

6. 直接调用

在函数不满足前面的场景,被直接调用时,this将指向全局对象。在浏览器环境中全局对象是Window,在Node.js环境中是Global

先来个简单的例子。

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

func() // Window

来一个复杂的例子,外层的outerFunc就起个迷惑目的。

function outerFunc() {
  console.log(this) // { x: 1 }

  function func() {
    console.log(this) // Window
  }

  func()
}

outerFunc.bind({ x: 1 })()

7. 不在函数里

不在函数中的场景,可分为浏览器的<script />标签里,或Node.js的模块文件里。

1、在<script />标签里,this指向Window

2、在Node.js的模块文件里,this指向Module的默认导出对象,也就是module.exports

非严格模式

严格模式是在ES5提出的。在ES5规范之前,也就是非严格模式下,this不能是undefinednull。所以**在非严格模式下,通过上面七步口诀,如果得出this指向是undefinednull,那么this会指向全局对象。**在浏览器环境中全局对象是Window,在Node.js环境中是Global

例如下面的代码,在非严格模式下,this都指向全局对象。

function a() {
  console.log("function a:", this)
  ;(() => {
    console.log("arrow function: ", this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()

非严格模式下执行结果为:

微信截图_20210917100943.png

在严格模式下,执行同样的代码进行对比。记住要一次性将所有代码复制粘贴到控制台中,才能运行在严格模式下(因为第一行 “use strict” 才会对后面的代码生效)。

"use strict"

function a() {
  console.log("function a:", this)
  ;(() => {
    console.log("arrow function: ", this)
  })()
}

a()

a.bind(null)()

a.bind(undefined)()

a.bind().bind(2)()

a.apply()

严格模式下执行结果为:

微信截图_20210917101028.png

七步口诀在严格模式下和非严格模式下都是完备的,只是在非严格模式下nullundefined会被转换为全局对象。所以我没有将这点列入口诀中。

做题复习

先背诵口诀再做题,“箭头函数、newbindapplycall、欧比届点(obj.)、直接调用、不在函数里”。

1. 下面代码执行后,func.count 值为多少?

function func(num) {
  this.count++
}

func.count = 0
func(1)

答案

func.count值为 0。

按照口诀,func()调用时属于第 6 类「直接调用」。在非严格模式下,this指向全局对象。thisfunc 一点关系都没有,所以 func.count保持不变so easy

2. 以下箭头函数中 this 指向谁呢?

obj = {
  func() {
    const arrowFunc = () => {
      console.log(this._name)
    }

    return arrowFunc
  },

  _name: "obj",
}

obj.func()()

func = obj.func
func()()

obj.func.bind({ _name: "newObj" })()()

obj.func.bind()()()

obj.func.bind({ _name: "bindObj" }).apply({ _name: "applyObj" })()

答案

// obj
// undefined
// newObj
// undefined
// bindObj

是不是很简单,你学废了吗?

推荐学习:JS视频教程

以上就是一文讲解js中this指向问题(附代码)的详细内容,更多请关注亿码酷站其它相关文章!


<!–亿码酷站直播班–>一文讲解js中this指向问题(附代码)
—–文章转载自PHP中文网如有侵权请联系ymkuzhan@126.com删除

下载声明:
  • 本站资源如无特殊说明默认解压密码为www.ymkuzhan.com建议使用WinRAR解压;
  • 本站资源来源于用户分享、互换、购买以及网络收集等渠道,本站不提供任何技术服务及有偿服务,资源仅提供给大家学习研究请勿作它用。
  • 赞助本站仅为维持服务器日常运行并非购买程序及源码费用因此不提供任何技术支持,如果你喜欢该程序,请购买正版!
  • 版权声明:
  • 下载本站资源学习研究的默认同意本站【版权声明】若本站提供的资源侵犯到你的权益,请提交版权证明文件至邮箱ymkuzhan#126.com(将#替换为@)站长将会在三个工作日内为您删除。
  • 免责声明:
  • 您好,本站所有资源(包括但不限于:源码、素材、工具、字体、图像、模板等)均为用户分享、互换、购买以及网络收集而来,并未取得原始权利人授权,因此禁止一切商用行为,仅可用于个人研究学习使用。请务必于下载后24小时内彻底删除,一切因下载人使用所引起的法律相关责任,包括但不限于:侵权,索赔,法律责任,刑事责任等相关责任,全部由下载人/使用人,全部承担。以上说明,一经发布视为您已全部阅读,理解、同意以上内容,如对以上内容持有异议,请勿下载,谢谢配合!支持正版,人人有责,如不慎对您的合法权益构成侵犯,请联系我们对相应内容进行删除,谢谢!