详解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 相关文章推荐
用js做一个小游戏平台 (一)
Dec 29 Javascript
js 动态文字滚动的例子
Jan 17 Javascript
JQuery表格内容过滤的实现方法
Jul 05 Javascript
jQuery实现带延迟效果的滑动菜单代码
Sep 02 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
Oct 26 Javascript
javascript正则表达式模糊匹配IP地址功能示例
Jan 06 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
Feb 13 Javascript
JS实现的加减乘除四则运算计算器示例
Aug 09 Javascript
解决vue2.0动态绑定图片src属性值初始化时报错的问题
Mar 14 Javascript
vue-auto-focus: 控制自动聚焦行为的 vue 指令方法
Aug 25 Javascript
js实现图片无缝循环轮播
Oct 28 Javascript
react-intl实现React国际化多语言的方法
Sep 27 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 setcookie() cannot modify header information 的解决方法
2009/01/09 PHP
关于PHP中Session文件过多的问题及session文件保存位置
2016/03/17 PHP
浅谈PHP的数据库接口和技术
2016/12/09 PHP
PHP登录验证功能示例【用户名、密码、验证码、数据库、已登陆验证、自动登录和注销登录等】
2019/02/25 PHP
laravel ORM关联关系中的 with和whereHas用法
2019/10/16 PHP
网站上面有这种切换效果
2006/06/26 Javascript
JavaScript Event事件学习第一章 Event介绍
2010/02/07 Javascript
使用javascript控制cookie显示和隐藏背景图
2014/02/12 Javascript
jquery 自定义容器下雨效果可将下雨图标改为其他
2014/04/23 Javascript
JavaScript实现添加、查找、删除元素
2015/07/02 Javascript
详解JavaScript数组的操作大全
2015/10/19 Javascript
JavaScript知识点总结(十)之this关键字
2016/05/31 Javascript
vue双向绑定的简单实现
2016/12/22 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
2017/02/09 Javascript
将 vue 生成的 js 上传到七牛的实例
2017/07/28 Javascript
页面缩放兼容性处理方法(zoom,Firefox火狐浏览器)
2017/08/29 Javascript
mint-ui 时间插件使用及获取选择值的方法
2018/02/09 Javascript
讲解vue-router之什么是编程式路由
2018/05/28 Javascript
vue axios请求频繁时取消上一次请求的方法
2018/11/10 Javascript
vue-loader中引入模板预处理器的实现
2019/09/04 Javascript
LayUi数据表格自定义赋值方式
2019/10/26 Javascript
记一次用ts+vuecli4重构项目的实现
2020/05/21 Javascript
JavaScript实现简单动态表格
2020/12/02 Javascript
python中的内置函数getattr()介绍及示例
2014/07/20 Python
Python中lambda的用法及其与def的区别解析
2014/07/28 Python
11个并不被常用但对开发非常有帮助的Python库
2015/03/31 Python
Python Property属性的2种用法
2015/06/21 Python
python利用pytesseract 实现本地识别图片文字
2020/12/14 Python
美国最大的珠宝商之一:Littman Jewelers
2016/11/13 全球购物
日常奢侈品,轻松购物:Verishop
2019/08/20 全球购物
区优秀教师事迹材料
2014/02/10 职场文书
帮一个朋友写的求职信
2014/08/09 职场文书
公司收款委托书范本
2014/09/20 职场文书
社区母亲节活动总结
2015/02/10 职场文书
使用canvas仿Echarts实现金字塔图的实例代码
2021/11/11 HTML / CSS
SQL Server实现分页方法介绍
2022/03/16 SQL Server