详解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.extend 函数的详细用法
Jun 27 Javascript
web前端设计师们常用的jQuery特效插件汇总
Dec 07 Javascript
JQuery实现展开关闭层的方法
Feb 17 Javascript
jQuery实现新消息在网页标题闪烁提示
Jun 23 Javascript
javascript实现数组去重的多种方法
Mar 14 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
Sep 25 Javascript
微信小程序canvas实现刮刮乐效果
Jul 09 Javascript
vue 指令之气泡提示效果的实现代码
Oct 18 Javascript
vue项目中实现的微信分享功能示例
Jan 21 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
May 10 Javascript
layui实现数据表格点击搜索功能
Mar 26 Javascript
如何使用Javascript中的this关键字
May 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-Fcgi下PHP的执行时间设置方法
2013/08/02 PHP
Yii2单元测试用法示例
2016/11/12 PHP
Thinkphp实现站点静态化的方法详解
2017/03/21 PHP
Laravel 模型使用软删除-左连接查询-表起别名示例
2019/10/24 PHP
JS中的prototype与面向对象的实例讲解
2013/05/22 Javascript
地址栏传递中文参数乱码在js里用escape转码
2013/08/28 Javascript
JavaScript实现的石头剪刀布游戏源码分享
2014/08/22 Javascript
node.js中的http.createClient方法使用说明
2014/12/15 Javascript
jQuery中click事件用法实例
2014/12/26 Javascript
jQuery实现限制textarea文本框输入字符数量的方法
2015/05/28 Javascript
基于jquery实现简单的手风琴特效
2015/11/24 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
简单实现jQuery级联菜单
2017/01/09 Javascript
微信小程序 video详解及简单实例
2017/01/16 Javascript
微信小程序手势操作之单触摸点与多触摸点
2017/03/10 Javascript
div中文字内容溢出常见的解决方法
2017/03/16 Javascript
微信小程序--组件(swiper)详细介绍
2017/06/13 Javascript
vue项目中在外部js文件中直接调用vue实例的方法比如说this
2019/04/28 Javascript
微信小程序吸底区域适配iPhoneX的实现
2020/04/09 Javascript
Vue CLI3移动端适配(px2rem或postcss-plugin-px2rem)
2020/04/27 Javascript
使用vue构建多页面应用的示例
2020/10/22 Javascript
[12:29]《一刀刀一天》之DOTA全时刻19:蝙蝠骑士田伯光再度不举
2014/06/10 DOTA
Python中matplotlib中文乱码解决办法
2017/05/12 Python
Python语言生成水仙花数代码示例
2017/12/18 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
pycharm恢复默认设置或者是替换pycharm的解释器实例
2018/10/29 Python
Python实现的批量修改文件后缀名操作示例
2018/12/07 Python
使用Flask-Cache缓存实现给Flask提速的方法详解
2019/06/11 Python
python文字转语音的实例代码分析
2019/11/12 Python
Django调用支付宝接口代码实例详解
2020/04/04 Python
Monki官网:斯堪的纳维亚的独立时尚品牌
2020/11/09 全球购物
媒矿安全生产承诺书
2014/05/23 职场文书
工程项目经理任命书
2014/06/05 职场文书
工厂见习报告范文
2014/10/31 职场文书
写自招自荐信的绝招!
2019/04/19 职场文书
浅谈Redis缓冲区机制
2022/06/05 Redis