详解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 相关文章推荐
popdiv
Jul 14 Javascript
javascript 循环调用示例介绍
Nov 20 Javascript
jquery实现炫酷的叠加层自动切换特效
Feb 01 Javascript
JavaScript弹出新窗口后向父窗口输出内容的方法
Apr 06 Javascript
JavaScript中Date.toSource()方法的使用教程
Jun 12 Javascript
javascript图片预加载实例分析
Jul 16 Javascript
javascript去掉代码里面的注释
Jul 24 Javascript
JS日期加减,日期运算代码
Nov 05 Javascript
jQuery Easyui学习之datagrid 动态添加、移除editor
Jan 27 Javascript
jQuery实现图片加载完成后改变图片大小的方法
Mar 29 Javascript
常用Javascript函数与原型功能收藏(必看篇)
Oct 09 Javascript
Vue实现图片轮播组件思路及实例解析
May 11 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闭包(Closure)使用详解
2013/05/02 PHP
解析yahoo邮件用phpmailer发送的实例
2013/06/24 PHP
弹出模态框modal的实现方法及实例
2017/09/19 PHP
让你的网站可编辑的实现js代码
2009/10/19 Javascript
JQUERY设置IFRAME的SRC值的代码
2010/11/30 Javascript
如何使用Jquery获取Form表单中被选中的radio值
2013/08/09 Javascript
Jquery操作下拉框(DropDownList)实现取值赋值
2013/08/13 Javascript
对之前写的jquery分页做下升级
2014/06/19 Javascript
浅析JSONP技术原理及实现
2016/06/08 Javascript
利用Vue.js实现求职在线之职位查询功能
2017/07/03 Javascript
Angular动画实现的2种方式以及添加购物车动画实例代码
2018/08/09 Javascript
Nodejs调用Dll模块的方法
2018/09/17 NodeJs
微信小程序实现通过双向滑动缩放图片大小的方法
2018/12/30 Javascript
Vue路由守卫及页面登录权限控制的设置方法(两种)
2020/03/31 Javascript
小程序表单认证布局及验证详解
2020/06/19 Javascript
[20:21]《一刀刀一天》第十六期:TI国际邀请赛正式打响,总奖金超过550万
2014/05/23 DOTA
深入解析Python的Tornado框架中内置的模板引擎
2016/07/11 Python
python高级特性和高阶函数及使用详解
2018/10/17 Python
Django文件上传与下载(FileFlid)
2019/10/06 Python
Python Django2.0集成Celery4.1教程
2019/11/19 Python
python对Excel的读取的示例代码
2020/02/14 Python
5分钟实现Canvas鼠标跟随动画背景
2019/11/18 HTML / CSS
印度首选时尚目的地:Reliance Trends
2018/01/17 全球购物
申报职称专业技术个人的自我评价
2013/12/12 职场文书
实习生岗位职责
2014/04/12 职场文书
工作分析计划书
2014/04/30 职场文书
演讲稿格式范文
2014/05/19 职场文书
企业宣传工作方案
2014/06/02 职场文书
2014年村支部书记四风对照检查材料思想汇报
2014/10/02 职场文书
2014年民主评议党员工作总结
2014/12/02 职场文书
联欢会开场白
2015/06/01 职场文书
2016年重阳节慰问信
2015/12/01 职场文书
八年级作文之友情
2019/11/25 职场文书
Python实现简繁体转换
2021/06/07 Python
浅谈Java实现分布式事务的三种方案
2021/06/11 Java/Android
MySQL日期时间函数知识汇总
2022/03/17 MySQL