JavaScript中的this的指向

this是JS的关键字,随着函数使用场合的不同,this值会发生变化。但总的原则是,this总是指向调用this所在函数的那个对象

1、纯函数调用

function test(){
this.x=1;
alert(x);
} 
test();

这里的this就是全局变量。看下面的例子就能很好的理解this就是全局对象Global。

var x=1;
function test(){
   alert(this.x);
}
test();  //1

var x=1;
function test(){
   this.x=0;
}
test();
alert(x);  //0

在JavaScript的变量作用域中规定,“全局变量都是window对象的属性。”因此执行test()时相当于window.test(),此时test函数体内的this关键字的指向变成了window对象。即将window对象的x变为0。

var x=1;
var b={
   x:2,
   getX:function(){
      return this.x;
   }
 };
alert(this.x);     //1
alert(b.getX()); //2

在上面的代码中,alert(this.x)中this指向window,所以在全局中搜寻x的值,为1;

alert(b.getX())中由于x所在函数作为对象b的方法被调用,this指向了b,因此在b中搜寻x的值,为2。

2、作为方法调用,那么this指调用方法的这个对象

function test(){
alert(this.x);
}
var o={};
o.x=1;
o.m=test;
o.m();  //1

3、作为构造函数调用。此时this指向新生成的对象。

function Test(){
   this.x=1;
}
var o= new Test();
alert(o.x);  //1

 4、apply调用。this指向的是apply中的第一个参数

var x=0;
function test(){
   alert(this.x);
}   
var 0={};
o.x=1;
o.m=test();
o.m.apply();  //0
o.m.apply(o);//1

 当apply没有参数时,表示为全局对象。所以值为0。

5、箭头函数中的this

箭头函数要实现类似纯函数的效果,必须剔除外部状态。所以当你定义一个箭头函数时,在普通函数里常见的this、arguments、caller都是没有的。

箭头函数里没有this。如下代码里可以取到this。这是为什么呢?

function foo(){
   let a=1;
   let b=()=>console.log(this.a);
   b();
}
foo();  //1

以上箭头函数中的this实际上是父级作用域中的this,即函数foo的this。箭头函数引用了父级的变量,构成一个闭包。以上代码等价于:

function foo(){
   let a=1;
   let self=this;
   let b=()=>console.log(selt.a);
   b();
}
foo();  //1

箭头函数不仅没有this,常用的arguments也没有。如果你能获取到arguments,那它一定是来自父作用域的。

function foo(){
   return ()=>console.log(arguments[0]);
}
foo(1,2)(3,4);  //1

上例中如果箭头函数有arguments,就应该输出的是3而不是1。

一个经常犯的错误是使用箭头函数定义对象的方法,如:

let a ={
    foo:1,
    bar:()=>console.log(this.foo)
};
a.bar();   //undefined

以上代码中,箭头函数中的this并不是指向a这个对象。对象a并不能构成一个作用域,所以再往上到达全局作用域,this就指向全局作用域。如果我们使用普通函数的定义方法,输出结果就符合预期,这是因为a.bar()函数执行时作用域绑定到了a对象。

let a ={
    foo:1,
    bar:function(){console.log(this.foo)}
};
a.bar();  //1

另一个错误是在原型上使用箭头函数。如:

function A(){
    this.foo=1; 
}
A.prototype.bar=()=>console.log(this.foo);
let a=new A;
a.bar();   //undefined 

同样,箭头函数中的this不是指向A,而是根据变量查找规则回溯到了全局作用域。同样,使用普通函数就不存在问题。在什么情况下使用箭头函数:

A、箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下。例如用在map、reduce、filter的回调函数定义中;

B、不要在最外层定义箭头函数,因为在函数内部操作this会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,将this控制在可见的范围内;

C、箭头函数最大的好处是简洁。在有多层函数嵌套的情况下,箭头函数的间接性并没有提升,反而影响了函数的作用范围的识别度,这种情况不建议使用箭头函数。

 

posted @ 2017-06-09 14:01  海盗洁哥  阅读(299)  评论(0编辑  收藏  举报