详解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 相关文章推荐
通过JAVASCRIPT读取ASP设定的COOKIE
Feb 15 Javascript
动态调用css文件——jquery的应用
Feb 20 Javascript
JavaScript中的常见问题解决方法(乱码,IE缓存,代理)
Nov 28 Javascript
解决WordPress使用CDN后博文无法评论的错误
Dec 15 Javascript
基于jQuery Ajax实现上传文件
Mar 24 Javascript
Adapter适配器模式在JavaScript设计模式编程中的运用分析
May 18 Javascript
基于jQuery实现点击列表加载更多效果
May 31 Javascript
深入浅析search 搜索框的写法
Aug 02 Javascript
ES6新数据结构Map功能与用法示例
Mar 31 Javascript
JS判断时间段的实现代码
Jun 14 Javascript
微信小程序实现pdf、word等格式文件上传的方法
Sep 10 Javascript
JS中多层次排序算法的实现代码
Jan 06 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的“It is not safe to rely on the system’s timezone settings”问题
2015/10/08 PHP
微信支付扫码支付php版
2016/07/22 PHP
jQuery库与其他JS库冲突的解决办法
2010/02/07 Javascript
ExtJs扩展之GroupPropertyGrid代码
2010/03/05 Javascript
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
2011/11/30 Javascript
jquery操作复选框(checkbox)的12个小技巧总结
2014/02/04 Javascript
JavaScript实现获得所有兄弟节点的方法
2015/07/23 Javascript
jquery实现很酷的网页顶部图标下拉菜单效果
2015/08/22 Javascript
js纯数字逐一停止显示效果的实现代码
2016/03/16 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
jQuery解决$符号命名冲突
2016/06/18 Javascript
ExtJS 4.2 Grid组件单元格合并的方法
2016/10/12 Javascript
移动设备手势事件库Touch.js使用详解
2017/08/18 Javascript
深入了解js原型模式
2019/05/30 Javascript
vue+axios实现post文件下载
2019/09/25 Javascript
关于angular浏览器兼容性问题的解决方案
2020/07/26 Javascript
[59:08]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第一局
2016/02/27 DOTA
[22:07]DOTA2-DPC中国联赛 正赛 iG vs Magma 选手采访
2021/03/11 DOTA
Matplotlib 生成不同大小的subplots实例
2018/05/25 Python
transform python环境快速配置方法
2018/09/27 Python
python批量从es取数据的方法(文档数超过10000)
2018/12/27 Python
python被修饰的函数消失问题解决(基于wraps函数)
2019/11/04 Python
Python hashlib模块加密过程解析
2019/11/05 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
使用python 将图片复制到系统剪贴中
2019/12/13 Python
matplotlib 画双轴子图无法显示x轴的解决方法
2020/07/27 Python
国际金融专业大学生职业生涯规划书
2013/12/28 职场文书
超市后勤自我鉴定
2014/01/17 职场文书
捐资助学倡议书
2014/04/15 职场文书
学生手册评语
2014/05/05 职场文书
美丽的大脚观后感
2015/06/03 职场文书
升学宴家长致辞
2015/07/27 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
超级实用!五步法则,教你写好年终工作总结
2019/12/05 职场文书
vue使用Google Recaptcha验证的实现示例
2021/08/23 Vue.js
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android