浅谈JavaScript中this的指向问题


Posted in Javascript onJuly 28, 2020

JavaScript中this指向问题

记得初学 JavaScript 时,其中 this 的指向问题曾让我头疼不已,我还曾私自将其与闭包、原型(原型链)并称 JS 武林中的三大魔头。如果你要想在 JS 武林中称霸一方,必须将这三大魔头击倒。个人认为在这三大魔头中,this 指向问题的武功最菜(难度最低)。俗话说柿子捡软的捏,那我们就先从 this 指向问题下手。

先记住攻克 this 指向问题的口诀(前辈们的总结):哪个对象调用函数,函数里的 this 就默认指向哪个对象(注意 this 只能指向对象)。这里说“默认指向”是因为我们通过箭头函数、call、apply、bind等手段来改变 this 的指向。现在我们只讨论 this 的默认指向。

全局作用域下以及全局作用域的函数中,this默认指向全局对象window

在严格模式下,全局作用域的函数中,this默认指向 undefined, 这是严格模式所规定的。

// 非严格模式下
console.log(this); // Window
function doSomething(){
 console.log(this); // Window
}
doSomething(); // 这里可以看成window.doSomething(),所以函数里的this指向全局对象window
// 严格模式下
'use strict';
console.log(this); // Window
function doInStrict(){
 console.log(this); // undefined
}
doInStrict();

对象里的函数,this指向该对象

var a = 1;
var obj = {
 a: 2,
 fn: function(){
  console.log(this); // {a: 2, fn: ƒ}
  console.log(this.a); // 2
 }
};
obj.fn();

上面函数被调用后,从打印结果可以看出此时 this 指向的是调用函数的对象 obj。如果将对象中的函数赋给全局对象中定义的变量 fn1,执行 fn1 又会出现什么结果呢?

var a = 1;
var obj = {
 a: 2,
 fn: function(){
  console.log(this); // Winidow
  console.log(this.a); // 1
 }
};
var fn1 = obj.fn;
fn1(); // 可以看成window.fn1();

从上面的例子可以看出,fn1 与 obj.fn 指向的函数是相同的,但是调用它的对象不同,那么函数中 this 的指向也就不一样了。

再看一个比较复杂的例子:

var a = 0;
function fn(){
	consoloe.log(this.a);
}
var obj1 = {
	a: 1,
	fn: function(){
		console.log(this.a);
	}
};
var obj2 = {
	a: 2,
	fn: function(){
		fn();
		obj1.fn();
		console.log(this.a);
	}
}
obj2.fn();

先说下执行结果,分别打印 0 1 2。当 obj2 调用 fn 函数时,先执行的是 fn(),这个函数是在全局作用域中定义的,该调用可以看成 window.fn(),所以,该函数内部的 this 指向的是 window 全局对象,this.a 自然就是全局对象中的 a 值(0)。

接着执行的是 obj1.fn(),它会从 obj1 中找到 fn 函数并执行。obj1 中的函数 fn 执行时调用它的对象是 obj1,所以,此时函数内部的 this 指向的就是 obj1 自身。那么 this.a 查到的值也就是对象 obj1 中 a 的值(1)。

最后打印函数中 this 所处的函数 fn 是被 obj2 调用的,那么自然而然 this 就指向了 obj2,所以 this.a 的结果就是 2 了。

从上面这个例子我们可以看出:函数内部 this 指向跟调用函数的对象有关,跟函数在哪里调用没有关系。

Window内置函数的回调函数中,this指向Window对象。

window 的内置函数( setInterval setTimeout 等),其回调函数中的 this 指向的是window对象。

var name = 'window';
var obj = {
 name: 'obj',
 func: function(){
  setTimeout(function () {
   console.log(this.name) // window
  },1000)
 }
}

obj.func()

但是一般在开发中,很多场景都需要改变 this 的指向。 请参考JS中this指向的更改,这里就不再赘述了。
this 既不指向函数自身也不指向函数的词法作用域,this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

找到函数直接调用的位置后用下面的几条规则就可以判断出 this 的绑定对象。

  1. 由 new 调用?绑定到新创建的实例对象上。
  2. 由 call、apply、bind调用?绑定到指定的对象上。
  3. 由上下文对象调用?绑定到那个上下文对象上。
  4. 默认:在严格模式下绑定到 undefined,否则绑定到全局对象 Window 上。
  5. ES6 中的箭头函数会继承外层函数调用的 this 绑定,这和 var self = this;的绑定机制一样。

到此这篇关于浅谈JavaScript中this的指向问题的文章就介绍到这了,更多相关JavaScript中this指向问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Javascript里使用Dom操作Xml
Jan 22 Javascript
javascript实现表格排序 编辑 拖拽 缩放
Jan 02 Javascript
JQuery中DOM实现事件移除的方法
Jun 13 Javascript
php利用curl获取远程图片实现方法
Oct 26 Javascript
js实现二级菜单渐隐显示
Nov 03 Javascript
微信小程序 Image API实例详解
Sep 30 Javascript
angular2+node.js express打包部署的实战
Jul 27 Javascript
Angular2.0/4.0 使用Echarts图表的示例代码
Dec 07 Javascript
关于HTML5的data-*自定义属性的总结
May 05 Javascript
关于单文件组件.vue的使用
Sep 20 Javascript
使用vue-router切换页面时,获取上一页url以及当前页面url的方法
May 06 Javascript
vue滚动tab跟随切换效果
Jun 29 Javascript
浅谈JavaScript中this的指向更改
Jul 28 #Javascript
Postman内建变量常用方法实例解析
Jul 28 #Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
Jul 28 #Javascript
解决Vue使用bus总线时,第一次路由跳转时数据没成功传递问题
Jul 28 #Javascript
解决vue bus.$emit触发第一次$on监听不到问题
Jul 28 #Javascript
vue+element-ui JYAdmin后台管理系统模板解析
Jul 28 #Javascript
vue实现虚拟列表功能的代码
Jul 28 #Javascript
You might like
在DC的漫画和电影中,蝙蝠侠的宿敌,小丑的真名是什么?
2020/04/09 欧美动漫
php可变长参数处理函数详解
2017/02/22 PHP
在IIS下安装PHP扩展的方法(超简单)
2017/04/10 PHP
php用wangeditor3实现图片上传功能
2019/08/22 PHP
PHPstorm激活码2020年5月13日亲测有效
2020/09/17 PHP
解读JavaScript代码 var ie = !-[1,] 最短的IE判定代码
2011/05/28 Javascript
JavaScript中window.open用法实例详解
2015/04/15 Javascript
nodejs实现获取当前url地址及url各种参数值
2015/06/25 NodeJs
jQuery layui常用方法介绍
2016/07/25 Javascript
深入理解JavaScript函数参数(推荐)
2016/07/26 Javascript
全面解析Node.js 8 重要功能和修复
2017/06/02 Javascript
Angular2.js实现表单验证详解
2017/06/23 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
vue仿淘宝订单状态的tab切换效果
2020/06/23 Javascript
jquery实现二级导航下拉菜单效果实例
2019/05/14 jQuery
JS把字符串格式的时间转换成几秒前、几分钟前、几小时前、几天前等格式
2019/07/10 Javascript
vue vantUI tab切换时 list组件不触发load事件的问题及解决方法
2020/02/14 Javascript
[01:39:04]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第二场 2月1日
2021/03/11 DOTA
详解使用pymysql在python中对mysql的增删改查操作(综合)
2017/01/18 Python
一文带你了解Python中的字符串是什么
2018/11/20 Python
python实现二维插值的三维显示
2018/12/17 Python
python画蝴蝶曲线图的实例
2019/11/21 Python
Python面向对象魔法方法和单例模块代码实例
2020/03/25 Python
Tensorflow--取tensorf指定列的操作方式
2020/06/30 Python
Python文件夹批处理操作代码实例
2020/07/21 Python
使用CSS3的appearance属性改变元素的外观的方法
2015/12/12 HTML / CSS
通往英国高街的商店橱窗:Down Your High Street
2020/07/19 全球购物
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
英语演讲稿3分钟
2014/04/29 职场文书
2014年党的群众路线学习心得体会
2014/11/05 职场文书
2014年医生工作总结
2014/11/21 职场文书
4S店客服专员岗位职责
2015/04/07 职场文书
卫生院艾滋病宣传活动总结
2015/05/09 职场文书
公司周年庆典致辞
2015/07/30 职场文书
JavaScript实现栈结构详细过程
2021/12/06 Javascript
Python OpenCV超详细讲解调整大小与图像操作的实现
2022/04/02 Python