针对JavaScript中this指向的简单理解


Posted in Javascript onAugust 26, 2016

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

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

例子1:

function a(){
  var user = "小J";
  console.log(this.user); //undefined
  console.log(this); //Window
}
a();

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

function a(){
  var user = "小J";   
console.log(this.user); //undefined console.log(this);
} 
window.a() //Window

和上面代码一样吧,其实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); //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 = "小J";
}
var a = new Fn();
console.log(a.user); //小J

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

除了上面的这些以外,我们还可以自行改变this的指向 ========>>> call, apply, bind 

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

function fn() 
{ 
  this.user = '小J'; 
  return {}; 
}
var a = new fn; 
console.log(a.user); //undefined

再看一个 

function fn() 
{ 
  this.user = '小J'; 
  return function(){};
}
var a = new fn; 
console.log(a.user); //undefined

再来 

function fn() 
{ 
  this.user = '小J'; 
  return 1;
}
var a = new fn; 
console.log(a.user); //小J
function fn() 
{ 
  this.user = '小J'; 
  return undefined;
}
var a = new fn; 
console.log(a.user); //小J

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

function fn() 
{ 
  this.user = '小J'; 
  return undefined;
}
var a = new fn; 
console.log(a); //fn {user: "小J"}

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

function fn() 
{ 
  this.user = '小J'; 
  return null;
}
var a = new fn; 
console.log(a.user); //小J

知识点补充: 
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就会被这个空的对象替代。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript窗口功能指南之在窗口中书写内容
Jul 21 Javascript
用正则获取指定路径文件的名称
Feb 27 Javascript
JavaScript传递变量: 值传递?引用传递?
Feb 22 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
Oct 11 Javascript
JavaScript设计模式之工厂模式和构造器模式
Feb 11 Javascript
理解javascript函数式编程中的闭包(closure)
Mar 08 Javascript
BootStrap 智能表单实战系列(二)BootStrap支持的类型简介
Jun 13 Javascript
jQuery网页定位导航特效实现方法
Dec 19 Javascript
vue监听input标签的value值方法
Aug 27 Javascript
js实现掷骰子小游戏
Oct 24 Javascript
vue 组件开发原理与实现方法详解
Nov 29 Javascript
谈一谈vue请求数据放在created好还是mounted里好
Jul 27 Javascript
轻松掌握JavaScript代理模式
Aug 26 #Javascript
轻松掌握JavaScript单例模式
Aug 25 #Javascript
很酷的星级评分系统原生JS实现
Aug 25 #Javascript
jQuery 利用$.ajax 时获取原生XMLHttpRequest 对象的方法
Aug 25 #Javascript
轻松掌握JavaScript策略模式
Aug 25 #Javascript
Javascript 6里的4个新语法
Aug 25 #Javascript
Javascript实现代码折叠功能
Aug 25 #Javascript
You might like
动易数据转成dedecms的php程序
2007/04/07 PHP
PHP程序级守护进程的实现与优化的使用概述
2013/05/02 PHP
使用ob系列函数实现PHP网站页面静态化
2014/08/13 PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
2016/07/21 PHP
PHP打印输出函数汇总
2016/08/28 PHP
PHP如何将图片文件上传到另外一台服务器上
2019/08/26 PHP
为jquery.ui.dialog 增加“在当前鼠标位置打开”的功能
2009/11/24 Javascript
使用JavaScript库还是自己写代码?
2010/01/28 Javascript
jquery实现点击弹出层效果的简单实例
2014/03/03 Javascript
ff chrome和ie下全局动态定位的异同及全局高度的取法
2014/06/30 Javascript
javascript使用appendChild追加节点实例
2015/01/12 Javascript
JavaScript获得指定对象大小的方法
2015/07/01 Javascript
网页收藏夹显示ICO图标(代码少)
2015/08/04 Javascript
JS基于FileSystemObject创建一个指定路径的TXT文本文件
2015/08/05 Javascript
js实现Select列表内容自动滚动效果代码
2015/08/20 Javascript
原生js实现回复评论功能
2017/01/18 Javascript
bootstrap为水平排列的表单和内联表单设置可选的图标
2017/02/15 Javascript
webstorm添加vue.js支持的方法教程
2017/07/05 Javascript
spirngmvc js传递复杂json参数到controller的实例
2018/03/29 Javascript
tracking.js页面人脸识别插件使用方法
2020/04/16 Javascript
深入浅析vue中cross-env的使用
2019/09/12 Javascript
JS运算符简单用法示例
2020/01/19 Javascript
[02:45]2016年中国刀塔全程回顾,完美“圣”典即将上演
2016/12/15 DOTA
python微信跳一跳系列之色块轮廓定位棋盘
2018/02/26 Python
Python 把序列转换为元组的函数tuple方法
2019/06/27 Python
scrapy数据存储在mysql数据库的两种方式(同步和异步)
2020/02/18 Python
pyspark 随机森林的实现
2020/04/24 Python
Amara美国站:英国高端家居礼品网站,世界各地的奢侈家具品牌
2017/07/26 全球购物
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
外贸业务员岗位职责
2013/11/24 职场文书
阳光体育活动方案
2014/02/16 职场文书
市政管理求职信范文
2014/05/07 职场文书
夫妻婚内购房协议书
2014/10/05 职场文书
离婚案件答辩状
2015/05/22 职场文书
给朋友的赠语
2015/06/23 职场文书