详解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宝典学习笔记
Feb 07 Javascript
JavaScript面向对象编程
Mar 02 Javascript
Jquery CheckBox全选方法代码附js checkbox全选反选代码
Jun 09 Javascript
JS TextArea字符串长度限制代码集合
Oct 31 Javascript
javascript 系统文件夹文件操作及参数介绍
Jan 08 Javascript
js中页面的重新加载(当前页面/上级页面)及frame或iframe元素引用介绍
Jan 24 Javascript
jQuery网页版打砖块小游戏源码分享
Aug 20 Javascript
Node.js Streams文件读写操作详解
Jul 04 Javascript
JS获取url参数、主域名的方法实例分析
Aug 03 Javascript
Web打印解决方案之证件套打的实现思路
Aug 29 Javascript
微信小程序新手教程之页面打开数量限制
Mar 03 Javascript
layui实现二维码弹窗、并下载到本地的方法
Sep 25 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面向对象之工作单元(实例讲解)
2017/06/26 PHP
Yii2.0框架模型添加/修改/删除数据操作示例
2019/07/18 PHP
Laravel5.5 实现后台管理登录的方法(自定义用户表登录)
2019/09/30 PHP
在 Laravel 中动态隐藏 API 字段的方法
2019/10/25 PHP
PHP扩展类型及安装方式解析
2020/04/27 PHP
MVVM模式中ViewModel和View、Model有什么区别?
2015/06/19 Javascript
JavaScript中对JSON对象的基本操作示例
2016/05/21 Javascript
使用BootStrap实现悬浮窗口的效果
2016/12/13 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
详解vuex 中的 state 在组件中如何监听
2017/05/23 Javascript
webpack+react+antd脚手架优化的方法
2018/04/02 Javascript
详解微信小程序缓存--缓存时效性
2019/05/02 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
总结Python编程中三条常用的技巧
2015/05/11 Python
Python实现类似比特币的加密货币区块链的创建与交易实例
2018/03/20 Python
Python pymongo模块用法示例
2018/03/31 Python
详解python多线程、锁、event事件机制的简单使用
2018/04/27 Python
详解python中的Turtle函数库
2018/11/19 Python
python实现WebSocket服务端过程解析
2019/10/18 Python
Django中的模型类设计及展示示例详解
2020/05/29 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
CSS3 border-radius圆角的实现方法及用法详解
2020/09/14 HTML / CSS
美国受信赖的教育产品供应商:Nest Learning
2018/06/14 全球购物
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
2013/07/06 面试题
计算机操作自荐信
2013/12/07 职场文书
酒店实习个人鉴定
2013/12/07 职场文书
大学生村官承诺书
2014/03/28 职场文书
雷人标语集锦
2014/06/19 职场文书
学生未请假就回家检讨书
2014/09/22 职场文书
道路交通事故赔偿协议书
2014/10/24 职场文书
2015年学校图书室工作总结
2015/05/19 职场文书
2016开学第一课心得体会
2016/01/23 职场文书
入党转正申请书范文
2019/05/20 职场文书
Oracle 数据仓库ETL技术之多表插入语句的示例详解
2021/04/12 Oracle
Oracle创建只读账号的详细步骤
2021/06/07 Oracle
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL