浅谈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模仿msgbox提示效果代码
Jun 10 Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 Javascript
关于javascript中this关键字(翻译+自我理解)
Oct 20 Javascript
javascript学习笔记(八) js内置对象
Jun 19 Javascript
js判断变量是否未定义的代码
Mar 28 Javascript
JavaScript获得url查询参数的方法
Jul 02 Javascript
jquery常用函数与方法汇总
Sep 01 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
Feb 16 Javascript
bootstrap+jQuery 实现下拉菜单中复选框全选和全不选效果
Jun 12 jQuery
本地存储localStorage用法详解
Jul 31 Javascript
JS实现获取word文档内容并输出显示到html页面示例
Jun 23 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
Aug 20 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
MySQL授权问题总结
2007/05/06 PHP
php array_merge下进行数组合并的代码
2008/07/22 PHP
PHP设计模式 注册表模式(多个类的注册)
2012/02/05 PHP
php中实现可以返回多个值的函数实例
2015/03/21 PHP
浅谈php提交form表单
2015/07/01 PHP
php变量与数组相互转换的方法(extract与compact)
2016/12/02 PHP
Ajax请求PHP后台接口返回信息的实例代码
2018/08/21 PHP
CI框架教程之优化验证码机制详解【验证码辅助函数】
2019/04/16 PHP
数组方法解决JS字符串连接性能问题有争议
2011/01/12 Javascript
jQuery 数据缓存模块进化史详细介绍
2012/11/19 Javascript
jquery获取元素值的方法(常见的表单元素)
2013/11/15 Javascript
javascript实现简单的鼠标拖动效果实例
2015/04/10 Javascript
JavaScript实现的多种鼠标拖放效果
2015/11/03 Javascript
js+flash实现的5图变换效果广告代码(附演示与demo源码下载)
2016/04/01 Javascript
Node.js调用fs.renameSync报错(Error: EXDEV, cross-device link not permitted)
2017/12/27 Javascript
基于vue-ssr服务端渲染入门详解
2018/01/08 Javascript
详解Vue 多级组件透传新方法provide/inject
2018/05/09 Javascript
实用Javascript调试技巧分享(小结)
2019/06/18 Javascript
selenium+java中用js来完成日期的修改
2019/10/31 Javascript
JavaScript Reflect Metadata实现详解
2019/12/12 Javascript
[01:23]一分钟告诉你 DOTA2为什么叫信仰2
2014/06/20 DOTA
Python中input和raw_input的一点区别
2014/10/21 Python
python实现挑选出来100以内的质数
2015/03/24 Python
使用Python的Flask框架实现视频的流媒体传输
2015/03/31 Python
老生常谈进程线程协程那些事儿
2017/07/24 Python
详解Python爬取并下载《电影天堂》3千多部电影
2019/04/26 Python
Django集成搜索引擎Elasticserach的方法示例
2019/06/04 Python
pyqt5之将textBrowser的内容写入txt文档的方法
2019/06/21 Python
Python3安装psycopy2以及遇到问题解决方法
2019/07/03 Python
python opencv把一张图片嵌入(叠加)到另一张图片上的实现代码
2020/06/11 Python
pip已经安装好第三方库但pycharm中import时还是标红的解决方案
2020/10/09 Python
scrapy头部修改的方法详解
2020/12/06 Python
美国男士西装打折店:Jos. A. Bank
2017/11/13 全球购物
群众路线领导班子四风对照检查材料
2014/09/27 职场文书
2016秋季田径运动会广播稿
2015/12/21 职场文书
浅谈Redis缓冲区机制
2022/06/05 Redis