深入理解javascript之this
javascript中的this含义很丰富,它能够是全局对象,当前对象或者是随意对象,这都取决于函数的调用方式。函数有下面几种调用方式:作为对象方法调用、作为函数调用、作为构造函数调用、apply或call调用。
对象方法调用
作为对象方法调用的时候。this会被绑定到该对象。
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
}
};
point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象
这里我想强调一点内容,就是this是在函数运行的时候去获取相应的值,而不是函数定义时。即使是对象方法调用,假设该方法的函数属性以函数名的形式传入别的作用域,也会改变this的指向。我举一个样例:
var a = {
aa : 0,
bb : 0,
fun : function(x,y){
this.aa = this.aa + x;
this.bb = this.bb + y;
}
};
var aa = 1;
var b = {
aa:0,
bb:0,
fun : function(){return this.aa;}
}
a.fun(3,2);
document.write(a.aa);//3,this指向对象本身
document.write(b.fun());//0,this指向对象本身
(function(aa){//注意传入的是函数。而不是函数运行的结果
var c = aa();
document.write(c);//1 , 因为fun在该处运行,导致this不再指向对象本身。而是这里的window
})(b.fun);
这样就明确了吧。这是一个easy混淆的地方。
函数调用
函数也能够直接被调用,这个时候this被绑定到了全局对象。
var x = 1;
function test(){
this.x = 0;
}
test();
alert(x); //0
但这样就会出现一些问题。就是在函数内部定义的函数。其this也会指向全局。而和我们希望的恰恰相反。代码例如以下:
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
// 内部函数
var moveX = function(x) {
this.x = x;//this 绑定到了全局
};
// 内部函数
var moveY = function(y) {
this.y = y;//this 绑定到了全局
};
moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>0
point.y; //==>0
x; //==>1
y; //==>1
我们会发现不但我们希望的移动呢效果没有完毕,反而会多出两个全局变量。
那么怎样解决呢?仅仅要要进入函数中的函数时将this保存到一个变量中,再运用该变量就可以。代码例如以下:
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
var that = this;
// 内部函数
var moveX = function(x) {
that.x = x;
};
// 内部函数
var moveY = function(y) {
that.y = y;
}
moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>1
point.y; //==>1
构造函数调用
在javascript中自己创建构造函数时能够利用this来指向新创建的对象上。
这样就能够避免函数中的this指向全局了。
var x = 2;
function test(){
this.x = 1;
}
var o = new test();
alert(x); //2
apply或call调用
这两个方法能够切换函数运行的上下文环境。也就是改变this绑定的对象。
apply和call比較类似,差别在于传入參数时一个要求是数组。一个要求是分开传入。所以我们以apply为例:
<pre name="code" class="html">var name = "window";
var someone = {
name: "Bob",
showName: function(){
alert(this.name);
}
};
var other = {
name: "Tom"
};
someone.showName(); //Bob
someone.showName.apply(); //window
someone.showName.apply(other); //Tom
能够看到,正常訪问对象中方法时,this指向对象。
使用了apply后,apply无參数时,this的当前对象是全局,apply有參数时,this的当前对象就是该參数。
箭头函数调用
这里须要补充一点内容。就是在下一代javascript标准ES6中的箭头函数的 this始终指向函数定义时的 this,而非运行时。我们通过一个样例来理解:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(function() {
this.func();
}, 100);
}
};
o.test(); // TypeError : this.func is not a function
上面的代码会出现错误,由于this的指向从o变为了全局。我们须要改动上面的代码例如以下:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
var _this = this;
setTimeout(function() {
_this.func();
}, 100);
}
};
o.test();
通过使用外部事先保存的this即可了。这里就能够利用到箭头函数了。我们刚才说过,箭头函数的 this始终指向函数定义时的 this,而非运行时。所以我们将上面的代码改动例如以下:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(() => { this.func() }, 100);
}
};
o.test();
这回this就指向o了,我们还须要注意一点的就是这个this是不会改变指向对象的,我们知道call和apply能够改变this的指向,可是在箭头函数中是无效的。
var x = 1,
o = {
x : 10,
test : () => this.x
}; o.test(); // 1
o.test.call(o); // 依旧是1
这样就能够明确各种情况下this绑定对象的差别了。
深入理解javascript之this的更多相关文章
- 深入理解javascript原型和闭包 (转)
该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...
- 深入理解JavaScript运行机制
深入理解JavaScript运行机制 前言 本文是写作在给团队新人培训之际,所以其实本文的受众是对JavaScript的运行机制不了解或了解起来有困难的小伙伴.也就是说,其实真正的原理和本文阐述的并不 ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- 深入理解javascript原型和闭包系列
从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解javascript原型和闭包(1)——一切都是对象
“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...
- 深入理解javascript原型和闭包(2)——函数和对象的关系
上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...
- 深入理解javascript原型和闭包(3)——prototype原型
既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...
- 深入理解javascript原型和闭包(4)——隐式原型
注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...
- 深入理解javascript原型和闭包(5)——instanceof
又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...
随机推荐
- Solr配置集群
1.主机SolrConfig.xml <requestHandler name="/replication" class="solr.ReplicationHand ...
- 使用POI进行Excel操作的总结一——创建Workbook,Sheet,Row以及Cell
前段时间,看在其他的网站上给出Excel文档的导入与导出操作,感觉很酷的样子,所以就学习了一下如何使用POI进行Excel的操作,现在对之前的学习过程进行一个总结. 一.现在普遍使用的Excel文档有 ...
- MySql数据库索引优化注意事项
设计好MySql的索引可以让你的数据库飞起来,大大的提高数据库效率.设计MySql索引的时候有一下几点注意: 1,创建索引 对于查询占主要的应用来说,索引显得尤为重要.很多时候性能问题很简单的就是因为 ...
- VBoxManage命令详解
转自:http://zhang-ly520.iteye.com/blog/300606 由于最近工作对vbox有一定涉猎,发现这个写的比较好,先转来,稍有空时再根据自己的心得整理一下. VBoxMan ...
- 妙用git rebase --onto指令
有时候,在分支提交更改的时候,会忘记rebase,就直接提交上去,或者忘记和本地远程分支做merge,就直接rebase了别的分支.有时候真希望有一种切片的方式,让自己的分支只需要接上某一段.这个时候 ...
- 打包静默安装参数(nsis,msi,InstallShield,InnoSetup)[转]
有时我们在安装程序的时候,希望是静默安装的,不显示下一步下一步,这编访问来教大家如何来操作,现在常用的制作安装程序的软件有, Microsoft Windows Installer , Windo ...
- HTML&CSS基础学习笔记1.32-选择器是什么
选择器是什么 选择器是CSS样式为了定位页面上的任意元素的一种方法. 选择器主要分为:元素标签选择器.通用选择器.类选择器.ID选择器.属性选择器.组合选择器.伪类选择器.伪元素选择器. 先做个了解, ...
- 安装KornShell(KSH)
Korn shell 是一个unix上的shell 程序,主要用在各种unix系统上,比如:sun/oracle unix,AIX等.ksh是有贝尔实验室的David korn开发出来的,ksh结合了 ...
- Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2)
Solr4.8.0源码分析(15) 之 SolrCloud索引深入(2) 上一节主要介绍了SolrCloud分布式索引的整体流程图以及索引链的实现,那么本节开始将分别介绍三个索引过程即LogUpdat ...
- 转:Zend Framework 2.0 分析
文章来自于:http://bbs.phpchina.com/thread-268362-1-1.html ZF2已经发布,与ZF1相比,MVC这一模块内部的实现机制可谓大相径庭,许多用过ZF1的PHP ...