由于js中this 是在运行期进行绑定的,所以js中的 this 可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式怎么区别:
1.this关键字在何处出现?
this他只能出现在函数中。当然在全局作用域中是个例外,意思是this只可能在两种情境下出现,一个是在函数体内,另一个是在全局作用域。
2.this是什么?
this是关键字,语言规范里规定他指向函数执行时的当前对象。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。
3.this到底指向哪?
首先明确this在JavaScript中和函数的执行环境而不是声明环境相关。
第一条中已经说过,this只能出现在函数中和全局作用域中,全局作用域中this指向全局对象(全局对象在浏览器这个环境中指window)。
如果this出现在函数中,那就要分情况来看this到底指向哪了。指向的依据就是函数的执行环境而不是声明环境。其实可以以一句话来概括就是this永远指向所在函数的所有者,当没有显示的所有者的时候,那么this指向全局对象。
4.各种情况下的this的具体指向?
(1).全局的作用域
1 console.log(this)
window调用所有,this指向window
注:(js变量作用域可分为:"全局变量"和"局部变量"。"全局变量":申明在函数之外的变量,"局部变量":申明在函数体中的变量,并且只能在当前函数体内访问,如:function(){var a = 0;}在申明变量是凡是没有var关键字,而直接赋值的变量均为全局变量)
(2).函数作为某个对象的成员方法调用
var name = "b";
var obj = {
name:"c",
fn:function(){
alert( this.name)
}
}
obj.fn();//c
在全局作用域中声明全局变量name,在obj对象中声明同时也声明一个name。当用对象obj调用他的成员方法fn的时候,this指向这个obj,因此打印出来的this.name为obj的name。
所以函数作为某个对象的成员方法调用时this指向该对象。
(3).函数作为函数直接使用
1 var name = "b"; 2 var obj = { 3 name:"c", 4 fn:function(){ 5 alert( this.name) 6 } 7 } 8 var obj1= obj.fn; 9 obj1();//b
同样的还是上边的一段代码,只不过这次我们把fn这个函数直接执行,这时在函数执行的时候他没有明确的当前对象,所以默认这时this就指向了全局对象。
所以函数作为函数直接使用时this指向全局对象。
(4).函数作为构造函数调用
var name = 'a'; function Obj () { this.name = 'b'; } Obj.prototype.getName = function () { console.log(this.name); } var myObj = new Obj(); myObj.getName();//b
函数作为构造函数调用时this指向用该构造函数构造出来的新对象。
(5).setTimeout(延迟)和setInterval(持续)以及匿名函数(函数调用模式就是指向window)
1 var name = "a"; 2 var obj = { 3 name: "b", 4 getName: function () { 5 setTimeout(function () { 6 console.log(this.name); 7 }, 1000); 8 }, 9 }; 10 11 obj.getName();//a
这两个函数执行的时候第一个参数可以为一个匿名函数,也可以是一个声明好的函数引用,所以this指向也就是指这个匿名函数或者函数引用的this的指向。通过第一条已经知道匿名函数或者在全局作用域中声明的函数直接执行的时候,其中的this指向全局对 象,所以在这里也一样,setTimeout和setInterval两者运行时,this指向全局对象。
这个时候如果还想输出的是b,也就是this指向obj的话就需要做点手脚了。
1 var name = "a"; 2 var obj = { 3 name: "b", 4 getName: function () { 5 var that = this; 6 setTimeout(function () { 7 console.log(that.name); 8 }, 1000); 9 }, 10 }; 11 12 obj.getName();//b
当然这样是改变不了this指向的,但是可以通过把this赋值给that,就实现了保存this指向的作用。
紧接着是匿名函数。
1 (function () { 2 console.log(this); 3 })()//window
匿名函数中的this指向全局对象,因为他没有显示的所有者。
(6)apply、call、bind
这三个函数是函数对象的一个方法,他们的作用就是为了改变函数执行时候的this指向,具体用法如下:
call:call(obj[,arg1][,arg2]);第一个参数为强制改变需要指向的对象,后边可选的是该函数的参数,如果不传obj的话默认为window。
apply:apply(obj[,arr]);第一个参数为强制改变需要指向的对象,后边可选的是该参数集合的数组形式,如果不传obj的话默认为window。
apply和call的作用和调用形式基本一致,不同的是call后面的参数与方法中是一一对应的,而apply的第二个参数是一个数组,数组中的元素是和方法中一一对应的,这就是两者最大的区别。两者都可以不传参数,此时默认改变指向的对象为全局对象。
bind:bind的调用形式和call相同,但是他返回的是改变调用对象后的函数引用,所以还要再执行一次,也就是obj.fun().bind()()。
总结:1.作为函数调用的时候,this指向全局对象(window)。2.作为对象的方法调用,this指向调用的对象(谁调用指向谁)。3.作为构造函数被调用的this指向新的对象(指向new出来的对象)。4.apply,call方法调用指向这些方法的第一个参数
原文地址!!!
by Aaron:http://www.cnblogs.com/aaronjs/archive/2011/09/02/2164009.html#_h1_6