详解JavaScript中关于this指向的4种情况


Posted in Javascript onApril 18, 2019

对很多前端开发者来说,JavaScript语言的this指向是一个令人头疼的问题。先看下面这道测试题,如果你能实现并解释原因,那本文对你来说价值不大,可以直接略过。

**开篇测试题:**尝试实现注释部分的Javascript代码,可在其他任何地方添加更多代码(如不能实现,说明一下不能实现的原因):

let Obj = function (msg) {
  this.msg = msg
  this.shout = function () {
   alert(this.msg)
  }
  this.waitAndShout = function () {
   // 隔5秒后执行上面的shout方面
   setTimeout(function () {
    let self = this
    return function () {
     self.shout()
    }
   }.call(this), 5000)
  }
 }

题目的参考答案在文末,但我不建议你直接查看答案,而是先阅读并思考文章的中的知识点。

一、在对象属性中的this指向问题

对象的属性是函数,那么函数中的this指向的是对象本身,即例子中的obj

var obj = {
  x: 123,
  fn: function () {
   console.log(this) // {x: 123, fn: ƒ}
   console.log(this.x) // 123
  }
 }
 obj.fn()

对象的属性是函数,函数内部还有函数,那么这个二级(及以上)函数的this指向的是window

var obj = {
  x: 456,
  fn: function () {
   console.log('fn', this) // {x: 456, fn: ƒ}
   var f1 = function () {
    console.log('fn.f1', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    console.log(this.x) // undefined
    var f2 = function () {
     console.log('fn.f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    }
    f2()
   }
   f1()
  }
 }
 obj.fn()

从上面的例子,我们可以总结出,对象属性中,嵌套超过一级及以上的函数,this指向都是window

二、构造函数中的this指向问题

构造函数中的一级函数,this指向通过构造函数new出来的实例(例子中的person)

var Person = function () {
  this.name = 'linlif'
  this.fn = function () {
   console.log('fn', this) // {name: "linlif", fn: ƒ}
  }
 }
 var person = new Person()
 person.fn()

构造函数中的二级(及以上)函数,this指向的是window

var Person = function () {
  this.name = 'linlif'
  this.fn = function () {
   console.log('fn', this) // {name: "linlif", fn: ƒ}
   var f2 = function () {
    console.log('f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    var f3 = function () {
     console.log('f3', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    }
    f3()
   }
   f2()
  }
 }
 var person = new Person()
 person.fn()

从上面的例子,我们可以总结出,构造函数中,嵌套超过一级及以上的函数,this指向的都是window

三、全局上下文环境中this指向问题

全局上下文环境,this指向浏览器的window对象,例如:

// 全局的this
 console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
 console.log(this === window) // true

 // 全局的普通函数
 var global = function () {
  console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
 }
 global()

四、call()和apply()对this指向的影响

使用call()方法后,this指向call()方法的参数。使用apply()的结果和call()是一致的,这里不做赘述。关于call()和apply()用法的区别,请自行查询相关资料。

// 改变调用对象为gObj
 var gObj = {
  name: 'gName'
 }
 var aaa = function () {
  console.log(this) // {name: "gName"}
  console.log(this.name) // gName
 }
 aaa.call(gObj)
 
 // 改变调用对象为window
 var name = 'global'
 var bbb = function () {
  console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
  console.log(this.name) // global
 }
 bbb.call(this)

总结:这就是一些关于this的指向问题的个人理解了,如果发现不妥之处,欢迎在评论区指出,或者私信我。

彩蛋 开篇测试题的参考答案,仅供参考!(有意思的地方:题目中,函数名的第一个字母大写,已经暗示这是一个构造函数)

let Obj = function (msg) {
  this.msg = msg
  this.shout = function () {
   alert(this.msg)
  }
  this.waitAndShout = function () {
   // 隔5秒后执行上面的shout方面
   setTimeout(function () {
    let self = this
    return function () {
     self.shout()
    }
   }.call(this), 5000)
  }
 }

 let obj = new Obj('msg')
 obj.waitAndShout()

以上所述是小编给大家介绍的JavaScript中关于this指向的4种情况详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js 蒙版进度条(结合图片)
Mar 10 Javascript
js注意img图片的onerror事件的分析
Jan 01 Javascript
javascript 应用小技巧方法汇总
Jul 05 Javascript
jquery实现倒计时效果
Dec 14 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
May 07 Javascript
JavaScript中为事件指定处理程序的五种方式分析
Jul 27 Javascript
微信小程序自定义导航栏
Dec 31 Javascript
node后端服务保活的实现
Nov 10 Javascript
解决Vue @submit 提交后不刷新页面问题
Jul 18 Javascript
前端vue如何使用高德地图
Nov 05 Javascript
Vue实现boradcast和dispatch的示例
Nov 13 Javascript
javascript实现简单页面倒计时
Mar 02 Javascript
vue.js高德地图实现热点图代码实例
Apr 18 #Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
Apr 18 #Javascript
Vue的H5页面唤起支付宝支付功能
Apr 18 #Javascript
详解Vue中的scoped及穿透方法
Apr 18 #Javascript
Node.js对MongoDB进行增删改查操作的实例代码
Apr 18 #Javascript
Vue 进阶之路(三)
Apr 18 #Javascript
Vue自定义全局Toast和Loading的实例详解
Apr 18 #Javascript
You might like
使用PHP制作新闻系统的思路
2006/10/09 PHP
php&java(二)
2006/10/09 PHP
PHP中的排序函数sort、asort、rsort、krsort、ksort区别分析
2014/08/18 PHP
跟我学Laravel之视图 & Response
2014/10/15 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
PHP笛卡尔积实现原理及代码实例
2020/12/09 PHP
JavaScript类型转换方法及需要注意的问题小结(挺全面)
2010/11/11 Javascript
javascript用户注册提示效果的简单实例
2013/08/17 Javascript
javascript 判断整数方法分享
2014/12/16 Javascript
深入理解JavaScript系列(22):S.O.L.I.D五大原则之依赖倒置原则DIP详解
2015/03/05 Javascript
jQuery中iframe的操作(点击按钮新增窗口)
2016/04/20 Javascript
Angular 输入框实现自定义验证功能
2017/02/19 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
2017/02/19 Javascript
微信小程序 图片加载(本地,网路)实例详解
2017/03/10 Javascript
Vue如何提升首屏加载速度实例解析
2020/06/25 Javascript
JS addEventListener()和attachEvent()方法实现注册事件
2021/01/11 Javascript
JavaScript代码实现微博批量取消关注功能
2021/02/05 Javascript
python运行时间的几种方法
2016/06/17 Python
socket + select 完成伪并发操作的实例
2017/08/15 Python
解决pycharm界面不能显示中文的问题
2018/05/23 Python
django 使用全局搜索功能的实例详解
2019/07/18 Python
tensorflow之自定义神经网络层实例
2020/02/07 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
Python字典fromkeys()方法使用代码实例
2020/07/20 Python
彻底解决Python包下载慢问题
2020/11/15 Python
Kaufmann Mercantile官网:家居装饰、配件、户外及更多
2018/09/28 全球购物
Brydge英国:适用于Apple iPad和Microsoft Surface Pro的蓝牙键盘
2019/05/16 全球购物
北美女性服装零售连锁店:maurices
2019/06/12 全球购物
解释下列WebService名词:WSDL、SOAP、UDDI
2012/06/22 面试题
物理系毕业生自荐信
2013/11/01 职场文书
保荐人的岗位职责
2013/11/19 职场文书
大跃进口号
2014/06/16 职场文书
安全生产先进个人事迹材料
2014/12/30 职场文书
班主任经验交流心得体会
2015/11/02 职场文书
python 实现mysql自动增删分区的方法
2021/04/01 Python
java协程框架quasar和kotlin中的协程对比分析
2022/02/24 Java/Android