详解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代码
Sep 02 Javascript
JavaScript Cookie的读取和写入函数
Dec 08 Javascript
js 多浏览器分别判断代码
Apr 01 Javascript
利用函数的惰性载入提高javascript代码执行效率
May 05 Javascript
jquery如何判断表格同一列不同行input数据是否重复
May 14 Javascript
jQuery插件实现大图全屏图片相册
Mar 14 Javascript
使用js获取地址栏参数的方法推荐(超级简单)
Jun 14 Javascript
JavaScript 深层克隆对象详解及实例
Nov 03 Javascript
使用jquery模拟a标签的click事件无法实现跳转的解决
Dec 04 jQuery
js核心基础之闭包的应用实例分析
May 11 Javascript
JS数组reduce()方法原理及使用技巧解析
Jul 14 Javascript
为什么node.js不适合大型项目
Apr 28 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 mcrypt可逆加密算法分析
2011/07/19 PHP
探讨Hessian在PHP中的使用分析
2013/06/13 PHP
9个实用的PHP代码片段分享
2015/01/22 PHP
PHP从FLV文件获取视频预览图的方法
2015/03/12 PHP
PHP处理bmp格式图片的方法分析
2017/07/04 PHP
js 页面传参数时 参数值含特殊字符的问题
2009/12/13 Javascript
jquery应该如何来设置改变按钮input的onclick事件
2012/12/10 Javascript
jquery中的查找parents与closest方法之间的区别
2013/12/02 Javascript
document.compatMode的CSS1compat使用介绍
2014/04/03 Javascript
如何改进javascript代码的性能
2015/04/02 Javascript
javascript实现五星评分功能
2015/11/10 Javascript
AngularJS API之copy深拷贝详解及实例
2016/09/14 Javascript
nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证示例
2016/12/30 NodeJs
微信小程序 Tab页切换更新数据
2017/01/05 Javascript
JS实现两周内自动登录功能
2017/03/23 Javascript
5个很好的Python面试题问题答案及分析
2018/01/19 Python
Python使用装饰器进行django开发实例代码
2018/02/06 Python
Python3.4 splinter(模拟填写表单)使用方法
2018/10/13 Python
Python实现定时自动关闭的tkinter窗口方法
2019/02/16 Python
pandas的qcut()方法详解
2019/07/06 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
python中图像通道分离与合并实例
2020/01/17 Python
PYcharm 激活方法(推荐)
2020/03/23 Python
Python的历史与优缺点整理
2020/05/26 Python
使用keras实现非线性回归(两种加激活函数的方式)
2020/07/05 Python
css3实现多个元素依次显示效果
2017/12/12 HTML / CSS
NARS化妆品官方商店:美国彩妆品牌
2017/08/26 全球购物
Booking.com亚太地区:Booking.com APAC
2020/02/07 全球购物
浅谈react路由传参的几种方式
2021/03/23 Javascript
跟单业务员岗位职责
2014/03/08 职场文书
优秀班组长事迹
2014/05/31 职场文书
大学生职业生涯十年规划书范文
2014/09/17 职场文书
个人简历求职信范文
2015/03/20 职场文书
2016教师学习党章心得体会
2016/01/15 职场文书
英语教学课后反思
2016/02/15 职场文书
2019年“我为祖国点赞”演讲稿(3篇)
2019/09/26 职场文书