详解js和jquery里的this关键字

《javaScript语言精粹》这本书中,把 this 出现的场景分为四类,简单的说就是:

1
2
3
4
5
6
7
有对象就指向调用对象

没调用对象就指向全局对象

new构造就指向新对象

通过 apply 或 call 或 bind 来改变 this 的所指。

函数调用模式中,thiswindow;方法调用模式中,this为方法所属的对象;构造器调用模式中,this为创建的新对象。

js中的this

我们要记住:this永远指向函数运行时所在的对象!而不是函数被创建时所在的对象。

this对象是在运行时基于函数的执行环境绑定的,在全局环境中,this等于window

先来看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<script>

var fullname = "Trigkit4";

var person = {

fullname : 'Jack',

prop:{

fullname : 'Blizzard',

getFullname : function () {

return this.fullname;

}

}

};



console.log(person.prop.getFullname());//Blizzard

var test = person.prop.getFullname;

console.log(test());//Trigkit4

</script>

getFullname被分配到test变量时,上下文指的是全局对象(window)。这是因为test是被隐式设置为全局对象的属性。出于这个原因,该函数返回windowfullname,所以在这里 this 指的是window, 所以返回的是第一个fullname

说明

this 关键字通常在对象的 构造函数中使用,用来引用对象。

关键字this:总是指向调用该方法的对象,如:

1
2
3
4
5
6
7
8
9
var iCar = new Object();

iCar.color = "red";

iCar.showColor = function(){

alert(this.color);//输出"red"

};

关键字this用在对象的showColor()方法中,在此环境,this等于iCar

使用this是因为在实例化对象时,总是不能确定开发者会使用什么样的变量名。使用this,即可在任意多个地方重用同一个函数。考虑下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function showColor(){

alert(this.color);

}

var oCar1 = new Object;

oCar1.color = "red";

oCar1.showColor = showColor;



var oCar2 = new Object;

oCar2.color = "blue";

oCar2.showcolor = showcolor;



oCar1.showColor();//输出"red"

oCar2.showColor();//输出"blue"

这段代码中,首先用this定义函数showColor(),然后创建两个对象oCar1oCar2,一个对象属性被设置为”red“,另一个为blue;两个对象都被赋予了属性showColor,指向原始的showColor()函数,调用每个showColor的方法,oCar1输出redoCar2输出blue

引用对象属性时,必须使用this关键字。

所有基于全局作用域的变量其实都是window对象的属性(property)。这意味着即使是在全局上下文中,this变量也能指向一个对象。

对于 JScript 的客户版本,如果在其他所有对象的上下文之外使用 this,则它指的是 window 对象。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

<head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />

<title></title>

<script type="text/javascript">

alert(this);//弹出 object window;

</script>


</head>

<body>



</body>

作为构造函数调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<script type="text/javascript">

function test(){

this.x = 10;

}



var obj = new test();

alert(obj.x); //弹出 10;

</script>

全局环境中的this

在看下面一个this出现在全局环境中的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type="text/javascript"> 

var name = "全局";

function getName(){

var name = "局部";

return this.name;

};

alert(getName());//弹出 全局;

</script>

函数getName()所处的对象是window对象,因此this也一定在window对象中。此时的this指向window对象,所以getName()返回的this.name其实是window.name,因此alert全局

结论:无论this身处何处,一定要找到函数运行时(或者说在何处被调用 了)的位置。

通过不同的调用语法,改变相同函数内部this的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type="text/javascript">

var foo = {

test:function(){

alert(this);

}

}

foo.test();//object,因为test方法在调用时属于foo对象



var baz = foo.test;

baz();//window,因为baz()被调用时属于global对象

</script>

局部环境中的this

看下面一个this出现在局部环境中的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

<script type="text/javascript">

var name = "全局";


var jubu={

name:"局部",

getName:function(){

return this.name;

}

};

alert(jubu.getName());

</script>

其中this身处的函数getName不是在全局环境中,而是处在jubu环境中。无论this身处何处,一定要找到函数运行时的位置。此时函数getName运行时的位置:

1
alert(jubu.getName());

显然,函数getName所在的对象是jubu,因此this的安身之处定然在jubu,即指向jubu对象,则getName返回的this.name其实是jubu.name,因此alert出来的是“局部”!

作用域链中的this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script type="text/javascript">

function scoping () {

console.log(this);



return function () {

console.log(this);

};

}



scoping()();

>>window

>> window

</script>

因为scoping函数属于window对象,自然作用域链中的函数也属于window对象。

对象中的this

可以在对象的任何方法中使用this来访问该对象的属性。这与用new得到的实例是不一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

var obj = {

foo: "test",

bar: function () {

console.log(this.foo);

}

};



obj.bar(); // "test"

重写this

无法重写this,因为它是一个关键字。

1
2
3
4
5
6

function test () {

var this = {}; // Uncaught SyntaxError: Unexpected token this

}

apply 和 call 调用以及 bind 绑定

applycall 调用以及 bind 绑定都是指向绑定的对象,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script type="text/javascript">

var bar = {

value: 'huang',

ages: 10

};

function foo(){

console.log(this);

}

console.log(foo());//window,函数没有所属对象:指向全局对象

console.log(foo.apply(bar));//即bar.foo(),this指向了bar,所以能读取该对象的所有属性

console.log(foo.call(bar));//ages: 10 value: "huang" __proto__: Object



var newFoo = foo.bind(bar);

console.log(newFoo());//Object

</script>

jquery中的this

$()生成的是什么呢?实际上$()=jquery(),那么也就是说返回的是一个jquery的对象。

$(this)jquery对象,能调用jquery的方法,例如click(), keyup()

1
2
3
4
5
6
7
8
9
10
11
 $(function () {

$('button').click(function () {

alert(this);//this 表示原生的DOM

//$(this)表示当前对象,这里指的是button

})

});

在许多情况下JQuerythis都指向HTML元素节点。

结论:

this,表示当前的上下文对象是一个html DOM对象,可以调用html对象所拥有的属性,方法。

$(this),代表的上下文对象是一个jquery的上下文对象,可以调用jquery的方法和属性值。