【转】彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题。
为什么要学习this?如果你学过面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西。
例子1:
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
a();
按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明。
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.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); //
}
}
}
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); //undefined
console.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,那么为什么对象a中会有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); //
为什么this会指向a?首先new关键字会创建一个空的对象,然后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。
2017-09-15 11:49:14
注意: 当你new一个空对象的时候,js内部的实现并不一定是用的apply方法来改变this指向的,这里我只是打个比方而已.
if (this === 动态的\可改变的) return true;
2016.12.21更新
</div>
【转】彻底理解js中this的指向,不必硬背。的更多相关文章
- 理解js中this的指向
学习自原文 http://www.cnblogs.com/pssp/p/5216085.html后的一点小结(原文作者总结的很棒^_^)! 关于js中this的指向,在函数定义的时候还无法 ...
- 彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 彻底理解js中this的指向
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 【转发】彻底理解 JS 中 this 的指向
为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,当然如果你有兴趣也可以看看,毕竟这是js中必须要掌握的东西. 例子1: f ...
- 如何简单理解js中this的指向
前序 每个人学js都会被this指向这个东西搞得很蒙,那就是this的指向问题.首先,我们要明白 this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上thi ...
- 彻底理解js中this的指向,不必硬背
来自 https://blog.csdn.net/u011088260/article/details/79230661 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行 ...
- 彻底理解js中this的指向,不必硬背(转)
转自: http://www.h5cn.com/js/jishu/2016/0226/18248.html 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定th ...
- 彻底理解 JS 中 this 的指向
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 如何更好的理解js中的this,分享2段有意思的代码
关于js中this的浅析,大家可以点击[彻底理解js中this的指向,不必硬背]这篇博客了解. 今天遇到2段比较有意思的代码. ----------------第一段----------------- ...
随机推荐
- Intent启动系统组件(activity,service,BroadReceiver)-android学习之旅(四十九)
android提供了统一的编程模型Intent来启动系统的组件,这样提供了松耦合性.是一种mvc的编程模式 $(function () { $('pre.prettyprint code').each ...
- 设计模式 - 装饰者模式(Decorator Pattern) 具体解释
装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...
- Hibernate的load()和get()区别
最近在用Hibernate的时候发现一个问题:比如我们从数据库获得一个对象时,使用session.get()方法还是session.load()? 两种方法在获得一个实体对象时是有区别的,在查询性能 ...
- OS X第三方类库管理工具cocoapods入门
一.简介 什么是cocoapods?--是OS X和iOS下一个第三方类库管理工具.通过cocoapods,可以为项目添加"Pods"依赖库,并且管理其版本. cocoapods好 ...
- 你为什么还坚持.NET
C#换什么比较合适? 从TIOBE来看,Java.C++.C.Python都好,对了,还不能忘了JS. Sql Server换什么比较合适? MySql挺好,Oracle也不错,也还有不少选择. 都挺 ...
- ASP.NET Core 使用 Redis 客户端
Mac OS 安装 Redis(用于连 Redis 服务器,方便查看数据):https://redis.io/topics/quickstart wget http://download.redis. ...
- 十六、Spring Boot 部署与服务配置
spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动.其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat).当然你也可以将项 ...
- Java中流-----个人总结心得
流 字符流 字节流 缓冲区 数据流---用于传输数据.IO流---Input/Output流.数据从外部流向程序---输入流:数据从程序流向外部的时候--输出流.读取一个文件---数据从文件流向程序- ...
- TableML Excel编译/解析工具
TableML TableML, Table Markup Language, 基于电子表格的标记语言, 类似JSON, XML, INI,TableML可以作为软件项目的配置标记语言, 与之不同的是 ...
- Asp.Net Web API(三)
Routing Tables路由表 在Asp.Net Web API中,一个控制器就是一个处理HTTP请求的类,控制器的public方法就被叫做action方法或简单的Action.当Web API接 ...