彻底理解js中this的指向

 

  首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉,那么接下来我会深入的探讨这个问题。

  为什么要学习this?如果你学过面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西。

 

例子1:

function a(){var user = "追梦子";console.log(this.user); //undefinedconsole.log(this); //Window
}
a();

按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。

function a(){var user = "追梦子";console.log(this.user); //undefinedconsole.log(this);  //Window
}
window.a();

和上面代码一样吧,其实alert也是window的一个属性,也是window点出来的。

例子2:

复制代码
var o = {user:"追梦子",fn:function(){console.log(this.user);  //追梦子}
}
o.fn();
复制代码

  这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。

 

其实例子1和例子2说的并不够准确,下面这个例子就可以推翻上面的理论。

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

本文出处:追梦子博客

例子3:

复制代码
var o = {user:"追梦子",fn:function(){console.log(this.user); //追梦子}
}
window.o.fn();
复制代码

  这段代码和上面的那段代码几乎是一样的,但是这里的this为什么不是指向window,如果按照上面的理论,最终this指向的是调用它的对象,这里先说个而外话,window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象。

  这里先不解释为什么上面的那段代码this为什么没有指向window,我们再来看一段代码。

复制代码
var o = {a:10,b:{a:12,fn:function(){console.log(this.a); //12}}
}
o.b.fn();
复制代码

  这里同样也是对象o点出来的,但是同样this并没有执行它,那你肯定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不准确,接下来我将补充一句话,我相信你就可以彻底的理解this的指向的问题。

  情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

  情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

  情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明,如果不相信,那么接下来我们继续看几个例子。

复制代码
var o = {a:10,b:{// a:12,fn:function(){console.log(this.a); //undefined}}
}
o.b.fn();
复制代码

尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

还有一种比较特殊的情况,例子4:

复制代码
var o = {a:10,b:{a:12,fn:function(){console.log(this.a); //undefinedconsole.log(this); //window}}
}
var j = o.b.fn;
j();
复制代码

这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。

  this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。

  this讲来讲去其实就是那么一回事,只不过在不同的情况下指向的会有些不同,上面的总结每个地方都有些小错误,也不能说是错误,而是在不同环境下情况就会有不同,所以我也没有办法一次解释清楚,只能你慢慢地的去体会。

 

构造函数版this:

function Fn(){this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子

  这里之所以对象a可以点出函数Fn里面的user是因为new关键字可以改变this的指向,将这个this指向对象a,为什么我说a是对象,因为用了new关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a创建了一个Fn的实例(相当于复制了一份Fn到对象a里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象a,那么this指向的自然是对象a,那么为什么对象Fn中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

  除了上面的这些以外,我们还可以自行改变this的指向,关于自行改变this的指向请看JavaScript中call,apply,bind方法的总结这篇文章,详细的说明了我们如何手动更改this的指向。

 

更新一个小问题当this碰到return时

复制代码
function fn()  
{  this.user = '追梦子';  return {};  
}
var a = new fn;  
console.log(a.user); //undefined
复制代码

再看一个

复制代码
function fn()  
{  this.user = '追梦子';  return function(){};
}
var a = new fn;  
console.log(a.user); //undefined
复制代码

再来

复制代码
function fn()  
{  this.user = '追梦子';  return 1;
}
var a = new fn;  
console.log(a.user); //追梦子
复制代码
复制代码
function fn()  
{  this.user = '追梦子';  return undefined;
}
var a = new fn;  
console.log(a.user); //追梦子
复制代码

什么意思呢?

  如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。

复制代码
function fn()  
{  this.user = '追梦子';  return undefined;
}
var a = new fn;  
console.log(a); //fn {user: "追梦子"}
复制代码

  还有一点就是虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。

复制代码
function fn()  
{  this.user = '追梦子';  return null;
}
var a = new fn;  
console.log(a.user); //追梦子
复制代码

知识点补充:

  1.在严格版中的默认的this不再是window,而是undefined。

  2.new操作符会改变函数this的指向问题,虽然我们上面讲解过了,但是并没有深入的讨论这个问题,网上也很少说,所以在这里有必要说一下。

function fn(){this.num = 1;
}
var a = new fn();
console.log(a.num); //1

  为什么this会指向a?首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

转载于:https://www.cnblogs.com/Julia-Yuan/p/6726049.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带码农《手写Mybatis》进度3:实现映射器的注册和使用

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 作者:小傅哥 博客:https://bugstack.cn 沉淀、分享、成长,让自己和他人都能有所收获&…

01背包问题,动态规划求解

01背包问题: 1.递归思想 0- 1 背包问题如果采用递归算法来描述则非常清楚明白, 它的算法根本思想是假设用布尔函数knap( s, n) 表示n 件物品放入可容质量为s 的背包中是否有解( 当knap 函数的值为真时 说明问题有解,其值为假时无解) . 我们可以通过输入s 和n 的值, …

SonarQube代码质量管理平台安装与使用

SonarQube代码质量管理平台安装与使用 注原文地址:http://blog.csdn.net/hunterno4/article/details/11687269Sonar简介 Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量 通过插件形式,可…

docker容器编排原来这么丝滑~

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 概念介绍&#xff1a…

互联网思维的“独孤九剑”

课前秀:三个段子 第一个段子:有一个毫无餐饮行业经验的人,他开了一家餐馆,菜品只有12道,在北京只有两家分店;仅两个月时间,就实现了所在商场餐厅坪效第一名;绿茶单位坪效大约是100元…

linux系统分析工具续-SystemTap和火焰图(Flame Graph)

本文为网上各位大神文章的综合简单实践篇,参考文章较多,有些总结性东西,自认暂无法详细写出,建议读文中列出的参考文档,相信会受益颇多。下面开始吧(本文出自 “cclo的博客” 博客,请务必保留此…

MySQL8.0.x 版本安装步骤傻瓜式教程【官方版】

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 MySQL8.0.x 安装 一、下载 MySQL官网下载链接:https://downloads.mysql.com/archives/community/ 选择版本后…

不用电的计算机(二)

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 转载请注明出处:https://blog.csdn.net/morningli/p/16058594.html 上一篇讲到最早的计算机是什么样的&#xf…

CocoaPods did not set the base configuration of your project 问题解决方案

今天在使用pod install的时候,出现了 [!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. In order for CocoaPods integration to work at all, please either set the base configuration…

在UnityUI中绘制线状统计图

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 先来个效果图 觉得不好看可以自己调整 1.绘制数据点 线状图一般由数据点和连线组…

HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面

错误原因为 IIS 扩展信息中午此扩展 标签: 今天,在vs2013中新建了一个placard.json文件,当我用jq读取它的时候,去提示404,直接在浏览器访问这个文件,提示: HTTP 错误 404.3 – Not Found 由于扩…

一行代码,让 VS Code 内置 PDF 阅读器变成深色模式

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 许多人会用 VSCode 写 LaTeX,等等,都会用到 PDF 预览。VSCo…

Selenium2Library+ride学习笔记

一、环境部署 1.安装python2.7编译环境、ride环境以及Selenium2Library环境,环境部署可参见前面几节。 2.启动RIDE编译环境,导入Selenium2Library库。     3. 执行F5,可查看Selenium2Library自带的关键字(Keyword)。 二、常用关鍵字解释 1. open b…

Android——线程通讯 Handler、Looper、Message;

线程通讯问题 (主要用到了Handler类,Looper类和Message类以及MessageQueue) 在Android中主线程如何向子线程中发送消息的问题。让我们来想想,这其中的过程,无非就是创建一个Handler对象,然后一个线程发消息…

Abp 实现通过手机号注册用户

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 前言 Abp 的 Identity 模块,实现了用户的管理,但是对于国…

Exchange 2010 创建设备室邮箱

其实创建设备邮箱和创建会议室邮箱都差不多,只是在新建邮箱的时候,邮箱的类型选择的不一样;1、打开Exchange管理控制台,展开“收件人配置”选择“邮箱”节点;在中间空白的地方右击选择“新建邮箱”;或者在操…

简单的Excel导出(两种方式)

最近项目里面有个周报Excel导出的功能,为了解决这个问题,我显示调研Excel内核的方式实现了,但是被告知该方法有诸多弊端(1、服务器需要装相应版本的Excel;2、如果程序中途出错服务器会有很多Excel进程)&…

一款开源的文件搜索神器,终于不用记 find 命令了

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 这是 HelloGitHub 推出的《讲解开源项目》系列,用一篇文章带你快速上…

C2审核模式(c2 audit mode)

C2审核模式(c2 audit mode)SQL Server C2 Audit 是为了满足美国国防部针对计算机的安全访问的安全评级要求而引入的。 SQL C2Audit 可以记录shutdown,restart,成功和失败的Login,成功或者失败访问数据库对象,所欲数据定义的执行,数…

开发者必读:2022年移动应用趋势洞察白皮书

Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https://blog.csdn.net/m0_56069948/article/details/122285941 华为开发者联盟与艾瑞咨询联合发布《2022年移动应用趋势洞察白皮书》,本…