-
JavaScript中的this
如果读者以前用的是java,在初学Javascript的时候可能会有些迷惑。在Java里,一个函数在定义完成后,this的指向就不会变化了。而在Javascript里,this不仅受函数定义的环境影响,还会受到调用方式影响。这也是为什么Javascript的this有时候容易让人感到混淆。
-
this 原理
在调用一个函数或方法的时候,我们可以传入一些参数,此时,有一个隐性的参数(implicit parameter)会协同我们定义的参数一起被传递给被调用的函数。而这个隐性参数名称就叫this。因此,要搞懂一个function里this的指向,实际上就是要明白在调用这个function的时候,什么东西会被当作this传递给函数。其实规则很简单,就是以下几种。
-
调用情形对this指向的影响
一、作为函数被调用
在非严格模式下,this指向 window object。
//定义
function foo() {
return this;
}
var foo2 = function () {
return this;
}
//调用
foo(); //得到 window Object
foo2(); //得到 window Object
复制代码
在严格模式下,this没有指向,指向 undefined。
//严格模式
"use strict";
//定义
function foo() {
return this;
}
var foo2 = function () {
return this;
}
//调用
foo(); //得到 undefined
foo2(); //得到 undefined
复制代码
二、作为方法被调用
和java等面向对象语言的思路一样,this指向调用它的对象。
function returnThis() {
return this;
}
var foo = returnThis;
var objectA = {
foo: returnThis
};
var objectB = {
foo: returnThis
};
returnThis(); //得到 window Object
foo(); //得到 window Object
objectA.foo(); //得到 objectA Object
objectB.foo(); //得到 objectB Object
复制代码
三、作为构造函数被调用
function Dog(name) {
this.name = name;
}
var dog = new Dog('小黄');
console.log('dog.name'); //'小黄'
复制代码
当JavaScript引擎遇到关键字new的时候,就会分出一块内存创建一个空的对象,这个空对象就是this的指向。在构造函数中,通过对this进行操作就可以实现对这个空对象的操作,从而完成构造一个新对象。
在上面这个例子,流程是这样的:引擎遇到new关键字,创建一个空对象,接着调用Dog这个构造函数,根据构造函数的指令,给这个空对象创建一个name属性,赋值‘小黄’,至此构造函数完成它的功能,最后创建完的对象被命名为dog。
另外可以发现,构造函数不需要return,因为构造函数的作用就是对一个空对象进行操作,最后默认返回this。如果我们手动return了除了Object之外的类型,比如数字、字符串等,这个return会被忽略。如果return了Object类型,这个Object会替代构造的对象返回。下面这几个例子和这篇主题无关,读者权当兴趣观看。
function Dog(name) {
this.name = name;
return '1'; //这行没有作用,会被引擎忽略
}
var dog = new Dog('小黄');
console.log('dog.name'); //'小黄'
复制代码
function Dog(name) {
this.name = name;
return {
name: '皮皮'
};
}
var dog = new Dog('小黄');
console.log('dog.name'); //'皮皮'
复制代码
歪楼:如果想让第一个例子中的return '1' 起作用,调用的时候去掉关键字 new 就可以了。这时候Dog()就会被当作普通函数调用,return自然就有作用了。而作为普通函数调用,this指向 window Object,此时浏览器的 window Object 会被赋予一个名叫'小黄'的 name 属性。(?)
四、apply和call中的this
apply()和call()是JavaScript中Function类型prototype中的方法。来看看call()中this的指向:
function foo() {
return this;
}
//如果此时直接调用foo(), this指向 window 或者 undefined,取决于是否是严格模式(复习第一节)
//定义一个新对象
var obj = {};
//调用foo的call方法
foo.call(obj, arg1, arg2, ···);
//arg1, arg2等参数会被传递给foo。在调用call时,foo中的this不再指向window或undefined,而是指向call的第一个参数,也就是本例中的obj。
//如果用apply只是参数传递的形式不一样:只采用一个数组传递;而call则是多个分开传递
//foo.apply(obj, [arg1, arg2]);
复制代码
具体例子:
function dog(name) {
return (this.name = name);
}
//定义一个新对象
var obj = {};
//调用foo的call方法
dog.call(obj, '小黄');
console.log('obj.name'); //返回'小黄'
复制代码
- 总结
至此「JavaScript this 指向简明阐述」总结完毕。
(完)