this 关键字在JavaScript中也算是相当复杂的了,它被定义在所有的函数的作用于中。
之前用this总是模棱两可,能用对,但是有时候真正解释的时候,说着说着自己都被绕迷糊了。请各路大神给以指点,有出入的地方给以纠正~
我们在知道怎么做之前,我们需要先明白为什么!
不要老是看别人用的this怎么用的,要先明白别人为什么要用它!!
首先看一段用this的代码,然后分析为什么用它:
function transform(){
return this.name.toUpperCase();
}
function statement(){
var myState = "Hello, I'm "+transform.call(this);
console.log(myState);
}
var me = {
name:"Pakar"
};
var you = {
name:"Lucy"
};
transform.call(me);//PAKAR
transform.call(you);//LUCY
statement.call(me);//Hello,I'm PAKAR
statement.call(you);//Hello,I'm LUCY
这段代码使用this来实现的,下面我们不使用this,通过给它传递参数(一个上下文对象)来实现一下:
function transform(context){
return context.name.toUpperCase();
}
function statement(context){
var myState = "Hello, I'm "+transform(context);
console.log(myState);
}
var me = {
name:"Pakar"
};
var you = {
name:"Lucy"
};
transform(me);//PAKAR
transform(you);//LUCY
statement(me);//Hello,I'm PAKAR
statement(you);//Hello,I'm LUCY*/
通过上面两端代码的对比,想必你也发现了,在不使用this的情况下,我们显式的传递了一个context。然而,使用this这样隐式的传递一个对象的引用,是不是很简洁又容易复用呀~
再补一个例子
//为对象中的方法指定一个 this
var obj = {
name: 'Pakar',
foo: function () {
console.log(this);
}
}
var obj2 = {
name: 'Lucy'
};
obj.foo.call(obj2);// Object {name: "Lucy"}
显式传递:
var obj = {
name: 'Pakar',
foo: function (context) {
console.log(context);
}
}
var obj2 = {
name: 'Lucy'
};
obj.foo(obj2);
如果你一直用显式的方式传递的话,你会发现代码越来越混乱,使用this就好多啦。同时也能够自动引用。
有时候我们太在意这个单词的字面意思,就会造成一些误解。
一般有两种错误的误解:
* 指向自身
* this指向函数的作用域(有点复杂,有些情况正确,其他情况却是错误)
这是两个很常见的误解
先看一个例子:
function foo(num){
console.log("foo: "+num);
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 */
//window i foo
//foo num 当执行到foo.count=0时候,向函数对象添加一个属性count
console.log(foo.count); //0
console.log(count);//NaN
这里我们会发现foo{…}执行了4次,foo.count仍然是0,要是还说this是指向自身的话,应该就是错误了吧,这就是this的误解之一,并不是都指向自身。
分析代码:
执行到foo.count=0时候,向函数对象添加一个属性count。函数内部的this.count并不是指向那个函数的this。那这个函数里面的count是哪个count呢?我们在window下面输出的值是NaN,可以看出,这个count是全局变量count。这是怎么造成的呢?
这造成的真正原因就是JS词法作用域
词法作用域,也可以说代码作用域,代码在编写时候体现出来的作用范围,代码一写好,你不用执行,作用范围就已经确定好了,这就是词法作用域。
整个代码只有函数可以限定作用域
所以在foo函数里面,并没有count,所以就会像它的父级函数找,在非严格模式下window会声明这个count,这个时候count为undefined,所以++会返回NaN;
有时候误解this指向函数的作用域,某种情况下它正确,其他情况却错误。
this在任何情况下都不指向函数的词法作用域。作用域和对象确实挺像。
function foo(){
var a = 2;
this.bar();
}
function bar(){
console.log(this.a);//undefined
}
foo();
这里想用this来引用函数的词法作用域,想引用foo的词法作用域,然后在bar里面操作foo作用域里面的a。刚才也说了this不指向函数的词法作用域,所以this也不可能在词法作用域中找到什么。
总结:
学习this首先要明白this既不指向函数自身也不指向函数的词法作用域。它在运行时进行绑定,不要想着在编写时,当然它的绑定和函数声明位置没什么关系!
this在函数被调用时发生绑定,它指向什么完全取决于函数在哪里被调用。