详解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 window.confirm确认 取消对话框实现代码小结
Oct 21 Javascript
JavaScript函数的4种调用方法详解
Apr 22 Javascript
javascript原生和jquery库实现iframe自适应高度和宽度
Jul 18 Javascript
jquery根据td给相同tr下其他td赋值的实现方法
Oct 05 Javascript
PHP捕捉异常中断的方法
Oct 24 Javascript
JS函数修改html的元素内容,及修改属性内容的方法
Oct 28 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
Mar 28 Javascript
Jquery把获取到的input值转换成json
May 15 jQuery
vue.js学习之vue-cli定制脚手架详解
Jul 02 Javascript
JS中this的指向以及call、apply的作用
May 06 Javascript
谈谈JavaScript中super(props)的重要性
Feb 12 Javascript
Vue 动态路由的实现及 Springsecurity 按钮级别的权限控制
Sep 05 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正则表达式使用的详细介绍
2013/04/27 PHP
解析zend studio中直接导入svn中的项目的方法步骤
2013/06/21 PHP
PHP反射类ReflectionClass和ReflectionObject的使用方法
2013/11/13 PHP
使用gd库实现php服务端图片裁剪和生成缩略图功能分享
2013/12/25 PHP
PHP正则提取不包含指定网址的图片地址的例子
2014/04/21 PHP
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
js触发select onchange事件的小技巧
2014/08/05 Javascript
JavaScrip常见的一些算法总结
2015/12/28 Javascript
jQuery Mobile页面返回不需要重新get
2016/04/26 Javascript
js实现可旋转的立方体模型
2016/10/16 Javascript
浅谈jQuery中的$.extend方法来扩展JSON对象
2017/02/12 Javascript
js仿网易表单及时验证功能
2017/03/07 Javascript
AngularJS之ionic 框架下实现 Localstorage本地存储
2017/04/22 Javascript
webpack学习笔记之代码分割和按需加载的实例详解
2017/07/20 Javascript
微信小程序中使用echarts的实现方法
2019/04/24 Javascript
微信小程序实现禁止分享代码实例
2019/10/19 Javascript
Vue $emit()不能触发父组件方法的原因及解决
2020/07/28 Javascript
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
[46:28]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.23
2019/09/05 DOTA
[48:18]DOTA2-DPC中国联赛 正赛 RNG vs Dynasty BO3 第二场 1月29日
2021/03/11 DOTA
python的几种开发工具介绍
2007/03/07 Python
Python 2.7.x 和 3.x 版本的重要区别小结
2014/11/28 Python
常见python正则用法的简单实例
2016/06/21 Python
Python实现扣除个人税后的工资计算器示例
2018/03/26 Python
Python数据结构之哈夫曼树定义与使用方法示例
2018/04/22 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
2019/06/05 Python
eBay澳大利亚站:eBay.com.au
2018/02/02 全球购物
法国发饰品牌:Alexandre De Paris
2018/12/04 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
《晏子使楚》教学反思
2014/02/08 职场文书
完美的中文自荐信
2014/05/24 职场文书
远程培训的心得体会
2014/09/01 职场文书
个人三严三实对照检查材料
2014/09/25 职场文书
学籍证明模板
2014/11/21 职场文书
公证处委托书
2015/01/28 职场文书
党员承诺书格式范文
2015/04/28 职场文书