深入理解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/ ...
随机推荐
- (转)PHP的ereg()与eregi()的不同及相同点。对比
ereg() 字符串比对解析. 语法: int ereg(string pattern, string string, array [regs]); 返回值: 整数/数组 函数种类: 资料处理 内容说 ...
- Python的参数模块OptionParser说明
可以替代getopt的一个模块 from optparse import OptionParser # 生成一个实例 parser = OptionParser(usage="%prog ...
- Objective-C学习篇04—多态
多态 多态的概念 有这样一个例子.早上我和同事说口渴了.结果:A同事拿着我的水杯去给我接了一杯水.B同事顺手在饮水机上拿了一次性纸杯给我接了杯水.C同事给了我一瓶他早上刚买的饮料.同事们得到的是同样的 ...
- Active控件有关问题
ActiveX 控件是允许网站提供视频等内容的网站. 当你浏览 Web 时,它们允许你使用工具栏.股票代号.视频和其它内容. 但是,这些程序有时可能出现问题,或者向你提供不需要的内容. 在某些情况下, ...
- 限制窗口拉伸范围——WM_GETMINMAXINFO
注意:此方法对CListCtrl的Report模式下的表头绘制有影响,用时需注意测试! 使用OnSizing的改进版 该例程用处为将窗口限制了大小,并且只允许上下拉伸.需要注意的是WM_GETMINM ...
- Neutron/ML2学习
Neutron/ML2 Neutron ML2 模块层2(ml2)插件是一种允许OpenStack网络同时地利用在复杂现实数据中心发现的各种第二层网络技术的框架.目前它与存在的openvswitch. ...
- CSS3重要内容翻译
以上是废话 1.3 此处未完全确认,相较于css3和css3的选择器,区别包括: 基础定义改变(选择器.选择器组,简单选择器等),特别的,作为css2中简单选择器,如今被成为简单选择器序列,“简 ...
- android异常之emulator-arm.exe已停止工作
我遇到的这个问题通过降低了AVD的分辨率后解决了,估计是电脑的显卡不行.
- POJ 3356(最短编辑距离问题)
POJ - 3356 AGTC Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Desc ...
- UITextFiled自动补全输入,选中补全内容。NSRange和UITextRange的相互转换。-b
有个需求就是 需要用户输入几位以后账号,可以根据本地存储的登录成功的账号,进行自动补全,并且补全内容为选中状态,不影响用户的新输入. 研究了一下,下面是完整的实现的方法. 补充个下载地址http:// ...