this指示器估计是很多人都会很头疼的一个东西,它的指向永远都让人觉得捉摸不定。今天我就通过这篇文章来记录一下我对this指示器的一些学习笔记与自己的理解。
如果有错误或者叙述不当的地方,请大家不吝赐教!
this是什么?
要理解this
的用法,就要先知道this
到底是何物。
this
在JS中是一个关键字,是指在函数运行时自动生成的一个内部对象,指向函数执行时的环境对象,换句话说this
也就是代表着是谁在调用这个函数。
this的几种应用场景
- 在全局环境中执行函数
var name = "hu";
function fn1(){
var name = "zhou";
alert(this.name);
alert(this);
};
fn1();
运行上面代码可以看到结果输出
hu;
[object Window]
可见在全局环境中执行函数,函数中this
指向的是全局对象window,window就是fn1执行时的环境对象。
- 函数作为对象的属性执行的时候
var name = "hu";
var obj = {
name : "zhou",
getName : function(){
alert(this.name);
alert(this);
}
};
obj.getName();
运行以上代码得到结果:
zhou;
[object Object];
可以很明显的看出来,输出的name
是obj对象中的name属性并非全局的name属性,this指向的是obj
对象。
此时obj就是调用getName函数的对象。getName函数是在obj的作用域下执行的。
- 在构造函数中使用
function Constructor(){
this.name = "hu";
this.age = "20";
}
var person = new Constructor();
alert(person.name);
alert(person.age);
运行以上代码会看到结果:
hu;
20;
person
是Constructor的一个实例,可以看出在通过new操作符创建Constructor的实例时this
指向的是person对象。
那么,创建实例这个过程是怎么实现的呢?为什么person
对象会是构造函数Constructor的环境对象呢?
那就需要了解通过new
来创建实例的过程:
-
首先创建一个Constructor的实例对象;
将对象的作用域绑定到这个对象;
再通过构造函数的内容初始化该对象;
构造函数返回该对象并赋值给person变量,当然person变量保存的是指向该对象的指针。
所以了解了new操作符创建实例的过程后this指向就很容易理解了
- 通过apply(),call()调用
apply()和call()函数一样,可以改变函数的执行环境对象。
var name = "hu";
var person = {
name : "zhou";
};
function fn1(){
alert(this.name);
}
fn1();
执行以上代码,可以看到结果为
hu;
因为在第一种情况中已经说明过,在全局环境中执行,this
指向的是全局对象。那边下面来改写代码:
fn1.apply(person);//fn1.call(person);
运行以上代码可以得到结果:
zhou;
这就是apply(),call()改变函数执行环境的作用,此时fn1的作用域就是person
对象,所以this指向的就是person对象。
- 事件侦听器
var target = $(" #target ");
window.click(function(eve){
alert(this);
alert(eve.target);
});
target.click();
执行以上代码可以看到结果:
[object Window];
[object HTMLELement];
从以上结果可以看出,当通过事件触发事件侦听器的时候,this指向的是事件的注册对象,而event.target指向的是事件触发是真正的对象。
那么,为什么要使用this呢?
首先看一段代码:
var getPersonName = (function(){
var person = {
name : "hu",
getName : getName
};
function getName(){
return person.name;
};
return person.getName;
})();
getPersonName();
在以上代码中,通过一个匿名函数创建了一个私有对象person,并把person的getName方法暴露给外界。
通过调用person.getName
方法可以正确的拿到person对象的name属性,但是这样的代码耦合程度太高,getName函数没有办法重用,只能用于person对象。
假设这样一个场景,假设有一天person的名字不再是person,改成dog了,那getName函数也得更改,如果只有一个person要改名还可以更改,但是如果成百上千的person都要改名呢?
所以可以改写如下代码:
function getName(){
return this.name;
}
这样改写getName函数之后可以降低函数与对象之间的耦合度,而且getName函数也可以在不同的对象中重用。
此篇博客就先到此,如果以后有更好的总结或者理解,我会补充更新。写的不好,请见谅。
说明:
- 版权声明:自由转载-非商用-非演绎-保持署名(创意共享3.0许可证)