详解JavaScript中的this指向问题


Posted in Javascript onFebruary 05, 2021

题记

JS中的this指向一直是个让初学者头疼的问题。今天,我们就一起来瞅瞅this倒地是咋回事,详细说说this指向原则,从此不再为了this指向操碎了心。

开篇

首先我们都知道this是Javascript语言的一个关键字。

它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它所在函数的对象。 那么接下来我们一步步探索下这个问题。

探索一

function a() {
  var user = "清蒸胖头鱼";
  console.log(this.name); //undefined
  console.log(this); //Window
 }
 a();
 window.a();//两种结果相同

如我们上文所说的this的最终指向的是那个调用它所在函数的对象,这里a其实是由window对象点出来的。

探索二

var obj = {
  name: '清蒸胖头鱼',
  f1: function () {
   console.log(this.name);//清蒸胖头鱼
  }
 };
 obj.f1();

再次强调一点this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁;这个例子this所在的f1函数是由obj对象调用的,所以这里的this指向obj对象。

探索三

如果要彻底的搞懂this必须看接下来的几个例子

var obj = {
  a: 5,
  b: {
   a: 10,
   fn: function () {
    console.log(this.a); //10
   }
  }
 };
 obj.b.fn();

不是说this的最终指向的是那个调用它所在函数的对象吗?这里为什么不指向obj对象呢?

这里需要补充三点:

  1. 如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window。
  2. 如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
  3. 如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

看到这相信大家基本掌握了this指向的原则了吧,再碎碎念一遍:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它所在函数的对象。

下面给大家介绍this几种不同的使用情况

构造函数(new 关键字)情况

function Student() {
  this.name = '清蒸胖头鱼';
 }
 var s1 = new Student();
 console.log(s1.name);// 清蒸胖头鱼

这里之所以对象s1可以点出函数Student里面的name 是因为new关键字可以改变this的指向,将这个this指向对象s1.

// new 关键字执行的过程
 1. 在函数体内创建一个空的对象.
 2. 让当前this指向这个空的对象.
 3. 通过this给当前空的对象添加键值对.
 4. 返回已经添加好所有键值对的对象给外面的变量.

定时器里的this指向情况

var num = 0;
 function Obj() {
  this.num = 1;
  this.getNum1 = function () {
   console.log(this.num);
  };
  this.getNum2 = function () {
   setInterval(function () {
    console.log(this.num);
   }, 1000);
  };
 }
 var o = new Obj();
 o.getNum1();//1  (o.num)
 o.getNum2();//0 (window.num)

o.getNum2()值之所以为0,也就是这里的this指向window,再拿出我们的this指向原则解释:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它所在函数的对象。

解: this.num所在的函数为定时器setInterval内的function () { console.log(this.num);},根据this指向原则当该函数被执行,this指向它的上一级对象。setInterval,又因setIntervalwindow点出了的,所以this指向window

callapplybind 改变指向情况

var num = 0;
 function Obj() {
  this.num = 1;
  this.getNum1 = function () {
   console.log(this.num);
  };
  this.getNum2 = function () {
   setInterval(function () {
    console.log(this.num);
   }.bind(this), 1000);//利用bind将this绑定到这个函数上
  };
 }
 var o = new Obj();
 o.getNum1();//1  (o.num)
 o.getNum2();//1 (o.num)

解释:

bind()方法是Function.prototype上的一个方法,当被绑定函数调用时,bind方法会创建一个新函数,并将第一个参数作为新函数的运行时的this。

根据原则:

没使用bind方法前:被调用时:this.num指向的是调用它所在函数的对象,也就是window.setTimeout对象。 使用bind方法后:被调用时:将原来的this重新指向到→调用getSum2函数(就是新this所在的函数)的对象。这里构造函数,通过new调用,所以指向o对象。

bind方法在该情况比较常用,当然如果使用callapply方法来代替也行,得到的结果也是正确的,但是callapply方法会在调用后马上执行,那样就没了延时的效果,定时器也就没有意义了。

以上就是详解JavaScript中的this指向问题的详细内容,更多关于JavaScript this指向的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树
Mar 24 Javascript
JS回调函数的应用简单实例
Sep 17 Javascript
探讨js字符串数组拼接的性能问题
Oct 11 Javascript
使用JS+plupload直接批量上传图片到又拍云
Dec 01 Javascript
什么是JavaScript中的结果值?
Oct 08 Javascript
fullCalendar中文API官方文档
Feb 07 Javascript
vue之数据交互实例代码
Jun 16 Javascript
vue2项目使用sass的示例代码
Jun 28 Javascript
Vue路由模块化配置的完整步骤
Aug 14 Javascript
vue实现微信浏览器左上角返回按钮拦截功能
Jan 18 Javascript
JS通用方法触发点击事件代码实例
Feb 17 Javascript
适用于 Vue 的播放器组件Vue-Video-Player操作
Nov 16 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
Feb 05 #Javascript
详解javascript脚本何时会被执行
Feb 05 #Javascript
前端如何实现动画过渡效果
Feb 05 #Javascript
原生js拖拽功能制作滑动条实例代码
Feb 05 #Javascript
jQuery是用来干什么的 jquery其实就是一个js框架
Feb 04 #jQuery
如何在JavaScript中使用localStorage详情
Feb 04 #Javascript
vue浏览器返回监听的具体步骤
Feb 03 #Vue.js
You might like
IStream与TStream之间的相互转换
2008/08/01 PHP
Laravel 5 框架入门(二)构建 Pages 的管理功能
2015/04/09 PHP
PHP简单读取xml文件的方法示例
2017/04/20 PHP
php 策略模式原理与应用深入理解
2019/09/25 PHP
PHP实现简单用户登录界面
2019/10/23 PHP
javascript之学会吝啬 精简代码
2010/04/25 Javascript
JavaScript日历实现代码
2010/09/12 Javascript
分享一个自定义的console类 让你不再纠结JS中的调试代码的兼容
2012/04/20 Javascript
js 获取、清空input type="file"的值示例代码
2014/02/19 Javascript
jQuery使用addClass()方法给元素添加多个class样式
2015/03/26 Javascript
使用Node.js处理前端代码文件的编码问题
2016/02/16 Javascript
JavaScript的React Web库的理念剖析及基础上手指南
2016/05/10 Javascript
ES5 ES6中Array对象去除重复项的方法总结
2017/04/27 Javascript
详解vue-cli + webpack 多页面实例配置优化方法
2017/07/13 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
vue2.0 实现富文本编辑器功能
2019/05/26 Javascript
js实现移动端吸顶效果
2020/01/08 Javascript
[50:27]Secret vs VG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
[01:02:26]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第二场 1月18日
2021/03/11 DOTA
Python 实现简单的shell sed替换功能(实例讲解)
2017/09/29 Python
css3个性化字体_动力节点Java学院整理
2017/07/12 HTML / CSS
HTML5 3D书本翻页动画的实现示例
2019/08/28 HTML / CSS
瑜伽服装品牌:露露柠檬(lululemon athletica)
2017/06/04 全球购物
Chemist Warehouse官方海外旗舰店:澳洲第一连锁大药房
2017/08/25 全球购物
香港网上花店:FlowerAdvisor香港
2019/05/30 全球购物
武汉英思工程科技有限公司–ORACLE面试测试题目
2012/04/30 面试题
办公室经理岗位职责
2014/01/01 职场文书
培训讲师邀请函
2014/01/10 职场文书
《找不到快乐的波斯猫》教学反思
2014/02/24 职场文书
信息服务专业毕业生求职信
2014/03/02 职场文书
小学教师师德承诺书
2014/05/23 职场文书
八一建军节慰问信
2015/02/14 职场文书
2015社区个人工作总结范文
2015/05/13 职场文书
上帝为你开了一扇窗之Tkinter常用函数详解
2021/06/02 Python
B站评分公认最好看的动漫,你的名字评分9.9,第六备受喜欢
2022/03/18 日漫
Android实现获取短信验证码并自动填充
2023/05/21 Java/Android