JS篇——javascript中的this

原创 2016年06月02日 14:55:00

  一直以来貌似都还没有更新js篇,本来是打算将css3和html5更新完之后再从头总结js,最后发现开始那些好像也没啥总结的,而且我这速度还不知道何时能把css3和html5总结完,所以就想到哪就更哪了,本来今天准备更新闭包,然后发现更新闭包之前,我最好先更新下js中的this关键字,所以这一篇更新js中的this关键字。

javascript中的this

在java中,this固定指向运行时的当前对象。但在javascript中,this的含义要多的多,它可以是全局对象、当前对象或者任意对象,完全取决于函数调用的方式。

this究竟指向哪里

一句话,javascript中的this指向的是执行时的当前对象,而不是声明时的当前对象。这句话什么意思,看下面例子。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };  
 var obj = test.show;
 obj();//1

上面这个例子最后弹出的是全局变量1,虽然this是在test.show里面声明的,但是执行的时候的对象却不是test,所以this不是指向的test对象,这是为啥呢,后面再说。

Javascript一共有四种调用模式:对象方法调用模式、纯函数调用模式、构造器调用模式以及apply调用模式。调用模式不同,对应的隐藏参数this值也会不同。

对象方法调用模式

函数作为对象的属性时,称为方法。此时函数(即方法)中的this对应是该对象。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
   } 
 };  
 test.show();//2
弹出2,此刻运行的是test对象的show属性,所以this指向test对象,所以当前对象是test对象。

然而,还有另外一种情况的方法调用,就是“this究竟指向哪里”中的例子。

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };  
 var obj = test.show;
 obj();//1
此时弹出的是1,此刻并不是调用了test这个对象的show属性,而是将test.show这个函数赋值给obj,又因为该函数是一个匿名函数,本身是没有对象的,所以show方法里的this就没有对象,没有对象就是window,window.x就是全局变量1。
谈到这里就顺便说一下setTimeout、setInterval和匿名函数中的“this”.

在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,浏览器中全局变量可以当成是window对象下的变量,例如:全局变量a,可以用window.a来引用。

var x=1;
 var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      },
      other:function(){
      	setTimeout(function(){
             alert(this.x);
      	}, 1000);
      }
    };  
test.other();//1
弹出1,这是因为setTimeout中的匿名函数运行时,匿名函数中的this指向window,所以window.x弹出1。setInterval与setTimeout类似。

怎样可以让上面例子弹出2呢?

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      },
      other:function(){
      	var that = this;
      	setTimeout(function(){
             alert(that.x);
      	}, 1000);
      }
    };  
test.other();//2

弹出2,这是因为在setTimeout中的匿名函数运行前,this指定的当前对象是test(这时运行的test对象的other属性),现将test对象赋值给that,setTimeout中的匿名函数运行后,改变的是this指定的对象,与that无关,that仍指定test对象。

这里再说一下setTimeout(函数名,延迟),setTimeout(匿名函数,延迟),setTimeout(字符串,延迟)这三的区别。以下面例子为例:

var x=1;
var test= {  
      x: 2,  
      show : function(){  
          alert(this.x);  
      } 
 };
setTimeout(函数名,延迟)(比如setTimeout(test.show(),1000))

test.show()是函数运行,这种传递方式真正传进去的是test.show()函数的返回值。如果是setInterval(test.show(),1000)这种方式只会执行test.show()一次,因为test.show()已经执行了,和setTimeout、setInterval其实没有关系

setTimeout(匿名函数,延迟)(比如setTimeout(test.show,1000))

这个相当于一个延时执行,传入了一个匿名函数,此时this变量是全局变量window,但是注意,它是没有传入函数参数的,如果函数有参数的话,建议使用闭包或者使用setTimeout(字符串,延迟)

setTimeout(字符串,延迟)比如setTimeout("test.show()",1000))

这个也相当于一个延时执行,用字符串代码创建了一个新的函数,因此该函数没有明确的对象,所以this指向全局变量。

var x = 1;  
var obj ={  
    x : 2,  
    show : function(){  
        alert(this.x);  
    },  
    other : function(){
        var that = this;
        setTimeout("that.show();", 1000);
    }
}; 
 
obj.other();//报错
纯函数调用模式

这种很简单,此时this就代表全局对象,即window。

function show(){
	this.x = 2;
	alert(this.x);
}
show();//2
var x = 1;
function show(){
	alert(this.x);
}
show();//1
var x = 1;
function show(){
	this.x = 2;
}
show();
alert(this.x);//2
构造器调用模式
构造器,就是生成一个新对象,这时,这个this就指这个新对象。

var x=1;
function show(){
	x=2;
	alert(x);
	alert(this.x);
	var x;
	alert(this.x);
	alert(x);
}
show();
上面弹出的结果是2,1,1,2

这就是上面说的那种情况,纯函数调用模式,这里的this对象就是全局对象window.

var x=1;
function show(){
	x=2;
	alert(x);
	alert(this.x);
	var x;
	alert(this.x);
	alert(x);
}
var test = new show();
test();
上面弹出的是2,undefined,undefined,2

这里的this对象就是new新创建的对象,新创建的对象里面并没有定义this.a,所以this.a为undefined。

apply调用模式

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象,因此,this指的就是这第一个参数。
call的用法和apply大致相同,只有一点区别,apply只接受两个参数,第一个参数和call相同,第二个参数必须是一个数组,数组中的元素对应的就是函数的形参。所以这里只主要讲一个apply。

var x=1;
function show(a){
	this.x = this.x+a;
	alert(this.x);
}
var obj = {
	x:0
};
show.apply();//NaN,apply()的参数为空时,默认调用全局对象,所以this.x为1,但此时show函数的参数中没有定义a,因此a为undefined,所以结果为NaN
show.apply(obj,[3]);//3,此时this对象为obj对象,所以this.x为0。0+3等于3。
show.call(obj,4);//7,此时this对象是obj对象,但因为上一步,所以现在obj中的x为3,3+4等于7





版权声明:本文为博主原创文章,未经博主允许不得转载。

JavaScript-高级进阶

day03-JavaScript高级 1、js的函数定义(三种方式)  一、使用关键字  function 方法名称(参数列表) { 方法体和返回值 }          注意1:参数列表中的参...
  • tujunyong
  • tujunyong
  • 2016年11月29日 23:50
  • 1300

JavaScript之$符号

JavaScript之$符号 前些天不小心用到了$符号,所以这里就来解释一下。 定义: $$()这个方法是在DOM中使用过于频繁的document.getElementById()方...
  • XXJ19950917
  • XXJ19950917
  • 2016年09月26日 10:53
  • 1755

Javascript中的<!-- //-->

Javascript中的
  • wangshuxuncom
  • wangshuxuncom
  • 2014年04月21日 18:56
  • 3766

javascript中&和&&的区别?

在Java中&和&&都是逻辑运算符,都是判断两边同时真则为真,否则为假;但是&&当第一个条件不成之后,后面的条件都不执行了,而&则还是继续执行,直到整个条件语句执行完为止。 javascri...
  • bz151531223
  • bz151531223
  • 2015年10月21日 16:25
  • 2471

在javascript中,哪些值能作为if的条件呢

在javascript中,哪些值能作为if的条件呢 1、布尔变量true/false 2、数字非0,非NaN        (0 或NaN) 见下面的例子,莫以为负数就以为if语句为假了。 var...
  • zh521zh
  • zh521zh
  • 2015年07月13日 11:13
  • 1193

javascript 中的onblur 事件

最开始的情况是这样的,在我们看一个电视镜头时,画面上有两个人,一远一近,如果远处的人在说话,我们将镜头位伸,焦点在远处的人身人,而近处的人就模糊了,而拉近时,近处的人会清晰,远处的人处于失焦的情况下就...
  • k_1991
  • k_1991
  • 2014年11月05日 09:35
  • 934

js中!!()的作用

我们知道JavaScript是一门弱类型的语言,但是,在使用中有时需要强制转化为相应的类型。所以,!!() ,这种写法有将弱类型转化为强类型的作用。这里提到类型转换不得不提两个概念:显式转换和隐式转化...
  • qq_31411389
  • qq_31411389
  • 2017年04月21日 17:50
  • 481

初识JavaScript(基础篇)

1 程序书写的位置 在页面中,”text/javascript”>标签对儿,里面就是书写JavaScript程序的地方。   1  2  3  text...
  • zyf__java
  • zyf__java
  • 2017年06月09日 23:36
  • 342

慕课网 Java遇见html-servlet篇

Servlet Servlet是在服务器上运行的小程序。 一个Servlet就是一个Java类,并且可以通过“请求”-“响应”编程模型来访问的这个驻留在服务器内存里的Servlet程序。   Tom...
  • yuhan_9204
  • yuhan_9204
  • 2015年12月23日 21:41
  • 1503

JavaScript之基础篇

自己的学习笔记,总结和Java的区别之处。
  • u013283727
  • u013283727
  • 2015年12月27日 20:51
  • 276
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JS篇——javascript中的this
举报原因:
原因补充:

(最多只允许输入30个字)