为什么要用this
我理解的this是执行上文的环境,和执行的地方很有关系。this提供了一种更优雅的方式来隐式“传递”一个对象的应用,就像下方的代码,可以把API设计的更加优雅。
function identify() {
return this.name.toUpperCase();
}
function speak() {
var greeting = "Hello, I'm " + identify.call( this );
console.log( greeting );
}
var me = {
name: "Kyle"
};
var you = {
name: "Reader"
};
identify.call( me ); // KYLE
identify.call( you ); // READER
speak.call( me ); // Hello, 我是 KYLE
speak.call( you ); // Hello, 我是 READER
误解
- This并不是指向函数本身。
function foo(num) {
console.log( "foo: " + num );
// 记录 foo 被调用的次数
this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
if (i > 5) {
foo( i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// foo 被调用了多少次?
console.log( foo.count ); // 0 -- WTF?
这里this.count是在运行的上下文上创建了一个count,这段代码是在window上创建的,和foo.count 不是一个变量。当然我们可以通过存储变量来解决这个问题,但是这样就不知道this的运行背后的原理。
如果我们想要在foo计算运行次数,改进的方式在于调用的时候的时候,请看下方代码:
function foo(num) {
console.log( "foo: " + num );
// 记录 foo 被调用的次数
// 注意,在当前的调用方式下(参见下方代码),this 确实指向 foo
this.count++;
}
foo.count = 0;
var i;
for (i=0; i<10; i++) {
if (i > 5) {
// 使用 call(..) 可以确保 this 指向函数对象 foo 本身
foo.call( foo, i );
}
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9
// foo 被调用了多少次?
console.log( foo.count ); // 4
- This指向函数作用域,某些请看是对的,其他时候不是正确的
function foo() {
var a = 2;
this.bar();
}
function bar() {
console.log( this.a );
}
foo(); // ReferenceError: a is not defined
这段代码是期望通过this能打通foo和bar的作用域,但是这是无法实现的。
This是在运行时进行绑定的,并不是编写时绑定,它的上下文取决于函数调用时各种条件。
当一个函数被调用时,会创建一个执行上下文,这个记录回包含函数在哪里被调用(调用栈),函数的调用方法,传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到
小结
- this 既不指向函数自身也不指向函数的词法作用域