灵活的理解JavaScript中的this指向


Posted in Javascript onFebruary 25, 2016

this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字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); //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 = "追梦子";
}
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指向的自然是对象,那么为什么对象Fn中会有user,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

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

灵活的理解JavaScript中的this指向对我们的工作有很大的帮助,同时感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 二维数组的实现与应用
Mar 16 Javascript
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 Javascript
js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动)
Dec 11 Javascript
JS实现鼠标单击与双击事件共存
Mar 08 Javascript
jquery easyui 结合jsp简单展现table数据示例
Apr 18 Javascript
jquery 实现滚动条下拉时无限加载的简单实例
Jun 01 Javascript
Summernote实现图片上传功能的简单方法
Jul 11 Javascript
jQuery操作cookie
Aug 08 Javascript
D3.js实现柱状图的方法详解
Sep 21 Javascript
利用prop-types第三方库对组件的props中的变量进行类型检测
May 02 Javascript
AngularJS中ng-class用法实例分析
Jul 06 Javascript
全选复选框JavaScript编写小结(附代码)
Aug 16 Javascript
jQuery插件实现表格隔行变色及鼠标滑过高亮显示效果代码
Feb 25 #Javascript
jQuery插件实现文字无缝向上滚动效果代码
Feb 25 #Javascript
jQuery zTree加载树形菜单功能
Feb 25 #Javascript
JavaScript实现搜索框的自动完成功能(一)
Feb 25 #Javascript
jquery插件之文字间歇自动向上滚动效果代码
Feb 25 #Javascript
jQuery插件ImageDrawer.js实现动态绘制图片动画(附源码下载)
Feb 25 #Javascript
利用jQuery中的ajax分页实现代码
Feb 25 #Javascript
You might like
在PWS上安装PHP4.0正式版
2006/10/09 PHP
PHP扩展CURL的用法详解
2014/06/20 PHP
php文件缓存方法总结
2016/03/16 PHP
thinkPHP5.0框架简单配置作用域的方法
2017/03/17 PHP
php数值转换时间及时间转换数值用法示例
2017/05/18 PHP
PHP单例模式与工厂模式详解
2017/08/29 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
页面版文本框智能提示JS代码
2009/11/20 Javascript
Jquery显示和隐藏元素或设为只读(含Ligerui的控件禁用,实例说明介绍)
2013/07/09 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
邮箱下拉自动填充选择示例代码附图
2014/04/03 Javascript
JavaScript学习笔记之定时器
2015/01/22 Javascript
js+HTML5基于过滤器从摄像头中捕获视频的方法
2015/06/16 Javascript
开启Javascript中apply、call、bind的用法之旅模式
2015/10/28 Javascript
动态的9*9乘法表效果的实现代码
2016/05/16 Javascript
jquery事件与绑定事件
2017/03/16 Javascript
js+html5实现页面可刷新的倒计时效果
2017/07/15 Javascript
原生JavaScript实现todolist功能
2018/03/02 Javascript
微信小程序实现运动步数排行功能(可删除)
2018/07/05 Javascript
优雅的将ElementUI表格变身成树形表格的方法步骤
2019/04/11 Javascript
Python 实现文件的全备份和差异备份详解
2016/12/27 Python
django实现同一个ip十分钟内只能注册一次的实例
2017/11/03 Python
Django项目中model的数据处理以及页面交互方法
2018/05/30 Python
对numpy.append()里的axis的用法详解
2018/06/28 Python
python实现求两个字符串的最长公共子串方法
2018/07/20 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
2019/07/26 Python
AmazeUI 列表的实现示例
2020/08/17 HTML / CSS
Gap中国官网:美式休闲风服饰
2017/02/05 全球购物
行政人员工作职责
2013/12/05 职场文书
一份关于丢失公司财物的检讨书
2014/09/19 职场文书
党的群众路线教育实践活动个人整改措施
2014/10/27 职场文书
委托书格式范文
2015/01/28 职场文书
2016年习总书记讲话学习心得体会
2016/01/20 职场文书
Spring-cloud Config Server的3种配置方式
2021/09/25 Java/Android
Win11怎么进入安全模式?Windows 11进入安全模式的方法
2021/11/21 数码科技
Vue3如何理解ref toRef和toRefs的区别
2022/02/18 Vue.js