关于 this

为什么要用this

this 提供了一种更优雅的方式来隐式”传递”一个对象引用。可以将API设计的更加简洁并且易于复用。
this既不是指向函数自身也不是指向函数的词法作用域。
this实际上是函数在被调用时发生的绑定,它指向什么完全取决于函数在哪调用

对this的误解

误区一 指向本身

如下代码,this并不是我们所想的那样指向函数本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

consolr.log语句产生了4条输出语句i,证明了foo(..)确实被调用了4次,但是foo.count仍然是0
执行foo.count =0 时,的确向函数对象foo添加了一个属性count,但是函数内部代码this.count中的this并不是指向那个函数对象,所以属性名同名,但对象并不相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function foo(num){
console.log("foo:"+num)
//记录函数foo被调用的次数
foo.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);//4

这个方法回避了this的问题,并且完全依赖于foo的词法作用域
另外一种方法强制this指向foo函数对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function foo(num){
console.log("foo:"+num)
//记录函数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,没有回避它

误区二 它的作用域

this在任何情况下都不指向它的词法作用域
如下段代码,试图跨越边界,使用this来隐式引用函数的词法作用域

1
2
3
4
5
6
7
8
function foo(){
var a = 2;
this.bar();
}
function bar (){
console.log(this.bar)
}
foo()//ReferenceError:a not a defined

这段代码试图使用this联通foo()和bar()的词法作用域,从而让bar()可以访问foo()作用域里的变量a。这是不可能实现的,使用this不可能在词法作用域中查到什么。
当一个函数被调用时,会创建一个活动记录(或者说执行上下文),这个记录会包含函数在哪里被调用,函数的调用方式,传入参数等信息,this就是这个记录的一个属性。会在函数的执行中用到
this实际上是函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

坚持原创技术分享,您的支持将鼓励我继续创作!