详解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 相关文章推荐
基于jquery完美拖拽,可返回拖动轨迹
Mar 29 Javascript
Jquery实现点击切换图片并隐藏显示内容(2种方法实现)
Apr 11 Javascript
js创建子窗口并且回传值示例代码
Jul 02 Javascript
深入剖析JavaScript中的枚举功能
Mar 06 Javascript
JavaScript数组Array对象增加和删除元素方法总结
Jan 20 Javascript
JavaScript判断是否为数组的3种方法及效率比较
Apr 01 Javascript
js实现头像图片切割缩放及无刷新上传图片的方法
Jul 17 Javascript
利用jQuery插件imgAreaSelect实现获得选择域的图像信息
Dec 02 Javascript
security.js实现的RSA加密功能示例
Jun 06 Javascript
v-slot和slot、slot-scope之间相互替换实例
Sep 04 Javascript
vue实现简单加法计算器
Oct 22 Javascript
详解vue 组件注册
Nov 20 Vue.js
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 中dirname(_file_)讲解
2007/03/18 PHP
PHP学习笔记之一
2011/01/17 PHP
基于php下载文件的详解
2013/06/02 PHP
THINKPHP2.0到3.0有哪些改进之处
2015/01/04 PHP
PHP常用设计模式之委托设计模式
2016/02/13 PHP
PHP正则+Snoopy抓取框架实现的抓取淘宝店信誉功能实例
2017/05/17 PHP
js实现的日期操作类DateTime函数代码
2010/03/16 Javascript
jquery下利用jsonp跨域访问实现方法
2010/07/29 Javascript
ExtJS实现文件下载的方法实例
2013/11/09 Javascript
用javascript读取xml文件读取节点数据
2014/08/12 Javascript
jQuery遮罩层实现方法实例详解(附遮罩层插件)
2015/12/08 Javascript
你有必要知道的25个JavaScript面试题
2015/12/29 Javascript
再次谈论React.js实现原生js拖拽效果引起的一系列问题
2016/04/03 Javascript
javascript之Array 数组对象详解
2016/06/07 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
2016/08/25 Javascript
jQuery设置Easyui校验规则(推荐)
2016/11/21 Javascript
HTML5canvas 绘制一个圆环形的进度表示实例
2016/12/16 Javascript
Angular.js中angular-ui-router的简单实践
2017/07/18 Javascript
vue项目前端知识点整理【收藏】
2019/05/13 Javascript
Servlet返回的数据js解析2种方法
2019/12/12 Javascript
JS操作Fckeditor的一些常用方法(获取、插入等)
2020/02/19 Javascript
TypeScript的安装、使用、自动编译的实现
2020/04/10 Javascript
[02:39]我与DAC之Newbee.Moogy:从论坛到TI
2018/03/26 DOTA
神经网络python源码分享
2017/12/15 Python
python中使用%与.format格式化文本方法解析
2017/12/27 Python
PyQt4实现下拉菜单可供选择并打印出来
2018/04/20 Python
Django 导出项目依赖库到 requirements.txt过程解析
2019/08/23 Python
Python如何实现的二分查找算法
2020/05/27 Python
Python中qutip用法示例详解
2020/10/02 Python
澳大利亚礼品卡商店:Gift Card Store
2019/06/24 全球购物
你的创业计划书怎样才能打动风投
2014/02/06 职场文书
珍惜资源保护环境的建议书
2014/05/14 职场文书
社会实践活动总结范文
2014/07/03 职场文书
党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2014年工人工作总结
2014/11/25 职场文书
公司财务制度:成本管理控制制度模板
2019/11/19 职场文书