详解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函数
May 27 Javascript
浅析js封装和作用域
Jul 09 Javascript
jquery删除指定的html标签并保留标签内文本内容的方法
Apr 02 Javascript
jquery验证邮箱格式是否正确实例讲解
Nov 16 Javascript
jQuery实现无限往下滚动效果代码
Apr 16 Javascript
jQuery插件实现文件上传功能(支持拖拽)
Aug 27 Javascript
JS实现获取当前URL和来源URL的方法
Aug 24 Javascript
js中toString()和String()区别详解
Mar 23 Javascript
正则表达式基本语法及表单验证操作详解【基于JS】
Apr 07 Javascript
详解node-ccap模块生成captcha验证码
Jul 01 Javascript
详解Vue基于vue-quill-editor富文本编辑器使用心得
Jan 03 Javascript
vue使用lodop打印控件实现浏览器兼容打印的方法
Feb 07 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
调频问题解答
2021/03/01 无线电
php 来访国内外IP判断代码并实现页面跳转
2009/12/18 PHP
WAMP环境中扩展oracle函数库(oci)
2015/06/26 PHP
关于php中的json_encode()和json_decode()函数的一些说明
2016/11/20 PHP
PHP编程实现阳历转换为阴历的方法实例
2017/08/08 PHP
zeroclipboard复制到剪切板的flash
2010/08/04 Javascript
jquery选择器的选择使用及性能介绍
2013/01/16 Javascript
JS验证身份证有效性示例
2013/10/11 Javascript
关于js中for in的缺陷浅析
2013/12/02 Javascript
JavaScript对象的property属性详解
2014/04/01 Javascript
jQuery html()方法使用不了无法显示内容的问题
2014/08/06 Javascript
基于javascript实现彩票随机数生成(升级版)
2020/04/17 Javascript
jQuery循环遍历子节点并获取值的方法
2016/04/14 Javascript
深入分析node.js的异步API和其局限性
2016/09/05 Javascript
jquery插件bootstrapValidator数据验证详解
2016/11/09 Javascript
微信小程序实现实时圆形进度条的方法示例
2017/02/24 Javascript
如何使用angularJs
2017/05/08 Javascript
jsTree事件和交互以及插件plugins详解
2017/08/29 Javascript
JavaScript常见鼠标事件与用法分析
2019/01/03 Javascript
微信小程序实现星星评分效果
2020/11/01 Javascript
使用vant的地域控件追加全部选项
2020/11/03 Javascript
Python3实现Web网页图片下载
2016/01/28 Python
Python 机器学习库 NumPy入门教程
2018/04/19 Python
Python模拟自动存取款机的查询、存取款、修改密码等操作
2018/09/02 Python
Python List列表对象内置方法实例详解
2019/10/22 Python
深入了解如何基于Python读写Kafka
2019/12/31 Python
Django多层嵌套ManyToMany字段ORM操作详解
2020/05/19 Python
jupyter使用自动补全和切换默认浏览器的方法
2020/11/18 Python
英国百安居装饰建材网上超市:B&Q
2016/09/13 全球购物
解释一下ArrayList Vector和LinkedList的实现和区别
2013/04/26 面试题
Java基础知识面试要点
2016/07/29 面试题
大学新生军训自我鉴定
2014/09/18 职场文书
毕业实习证明(4篇)
2014/10/28 职场文书
入伍通知书
2015/04/23 职场文书
求职信:会计求职的写作技巧
2019/04/24 职场文书
html原生table实现合并单元格以及合并表头的示例代码
2023/05/07 HTML / CSS