详解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正则表达式验证手机号,email地址,邮政编码
Jan 23 Javascript
jquery遍历checkbox介绍
Feb 21 Javascript
jquery使用$(element).is()来判断获取的tagName
Aug 24 Javascript
js实现九宫格图片半透明渐显特效的方法
Feb 16 Javascript
JQUERY表单暂存功能插件分享
Feb 23 Javascript
详解Bootstrap插件
Apr 25 Javascript
JavaScript中的对象继承关系
Aug 01 Javascript
简单理解vue中el、template、replace元素
Oct 27 Javascript
bootstrap制作jsp页面(根据值让table显示选中)
Jan 05 Javascript
JS简单判断字符在另一个字符串中出现次数的2种常用方法
Apr 20 Javascript
浅谈ajax在jquery中的请求和servlet中的响应
Jan 22 jQuery
vue实现路由不变的情况下,刷新页面操作示例
Feb 02 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新手上路(七)
2006/10/09 PHP
PHP的explode和implode的使用说明
2011/07/17 PHP
Laravel事件监听器用法实例分析
2019/03/12 PHP
js实现权限树的更新权限时的全选全消功能
2009/02/17 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
2010/11/17 Javascript
基于Jquery的简单图片切换效果
2011/01/06 Javascript
浅析jQuery EasyUI中的tree使用指南
2014/12/18 Javascript
javascript将数字转换整数金额大写的方法
2015/01/27 Javascript
举例简介AngularJS的内部语言环境
2015/06/17 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(一)
2015/12/10 Javascript
jquery插件格式实例分析
2016/06/16 Javascript
微信小程序tabbar不显示解决办法
2017/06/08 Javascript
AngularJS中filter的使用实例详解
2017/08/25 Javascript
Angular 4根据组件名称动态创建出组件的方法教程
2017/11/01 Javascript
js的函数的按值传递参数(实例讲解)
2017/11/16 Javascript
从零学Python之引用和类属性的初步理解
2014/05/15 Python
Pandas 数据框增、删、改、查、去重、抽样基本操作方法
2018/04/12 Python
使用python将请求的requests headers参数格式化方法
2019/01/02 Python
Python中的异常处理try/except/finally/raise用法分析
2019/02/28 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
Python 脚本的三种执行方式小结
2019/12/21 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
Django执行源生mysql语句实现过程解析
2020/11/12 Python
大女孩胸罩:Big Girls Bras
2016/12/15 全球购物
Nike挪威官网:Nike.com (NO)
2018/11/26 全球购物
护士长竞聘演讲稿
2014/04/30 职场文书
2014年销售内勤工作总结
2014/12/01 职场文书
2015年出纳个人工作总结
2015/04/02 职场文书
停车场管理制度范本
2015/08/05 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
护理自荐信
2019/05/14 职场文书
Redis5之后版本的高可用集群搭建的实现
2021/04/27 Redis
Mysql数据库命令大全
2021/05/26 MySQL
Python图片检索之以图搜图
2021/05/31 Python
Java练习之潜艇小游戏的实现
2022/03/16 Java/Android