Javascript this 关键字 详解
一、this指向构造函数实例化对象
在上篇文章中,我们提到了使用new和不使用new调用构造函数的区别,如下例:
functionBenjamin(username,sex){
   this.username=username;
   this.sex=sex;
}
varbenjamin=newBenjamin("zuojj","male");
//Outputs:Benjamin{sex:"male",username:"zuojj"}
console.log(benjamin);
varben=Benjamin("zhangsan","female");
//Outputs:undefined
console.log(ben);
当构造函数当做普通函数被调用时,并没有返回值,同时this指向全局对象。那么我们如何来避免因为缺少new关键字,而产生的问题呢?
functionBenjamin(username,sex){
 //Checkwhether"this"isa"Benjamin"object
 if(thisinstanceofBenjamin){
    this.username=username;
    this.sex=sex;
 }else{
  returnnewBenjamin(username,sex);
 }
}
varbenjamin=newBenjamin("zuojj","male");
//Outputs:Benjamin{sex:"male",username:"zuojj"}
console.log(benjamin);
varben=Benjamin("zhangsan","female");
//Outputs:Benjamin{username:"zhangsan",sex:"female"}
console.log(ben);
在上例中,我们首先检查this是否是Benjammin的实例,如果不是,使用new自动调用构造函数,并实例化,这意味着,我们不再需要担心,遗漏new关键字实例化构造函数。当然这样我们可能会养成一个坏的习惯,如果避免这种现象呢?我们可以抛出一个错误,像下面这样:
functionBenjamin(username,sex){
 //Checkwhether"this"isa"Benjamin"object
 if(thisinstanceofBenjamin){
    this.username=username;
    this.sex=sex;
 }else{
  //Ifnot,throwerror.
       thrownewError("`Benjamin`invokedwithout`new`");
 }
}
二、this指向调用该函数的对象
看下面的例子:
varx=10;
varobj={
 x:10,
 output:function(){
  //Outputs:true
  console.log(this===obj);
  returnthis.x;
 },
 innerobj:{
  x:30,
  output:function(){
   //Outputs:true
   console.log(this===obj.innerobj);
   returnthis.x;
  }
 }
};
//Outputs:10
console.log(obj.output());
//Outputs:30
console.log(obj.innerobj.output());
三、this指向全局对象
在上面讨论构造函数的时候我们也讨论到不适用new的时候,this会指向全局对象,下面我们来看看两种常见的容易犯错的实例:
varx=100;
varobj={
 x:10,
 output:function(){
  (function(){
   //Outputs:true
   console.log(this===window);
   //Outputs:Inner:100
   console.log("Inner:"+this.x);
  })();
  
  returnthis.x;
 }
};
//Outputs:10
console.log(obj.output());
在使用闭包的时候,作用域发生变化,this指向window(浏览器中)。
varx=100;
varobj={
 x:10,
 output:function(){
  returnthis.x;
 }
};
varoutput=obj.output;
//Outputs:10
console.log(obj.output());
//Outputs:100
console.log(output());
varobj2={
 x:30,
 output:obj.output
}
//Outputs:30
console.log(obj2.output());
此时this始终指向函数调用时的对象。
四、this指向apply/call()方法指派的对象
varx=100;
varobj={
 x:10,
 output:function(){
  returnthis.x;
 }
};
//Outputs:10
console.log(obj.output());
varobj2={
 x:40,
 output:obj.output
}
//Outputs:40
console.log(obj.output.call(obj2));
//Outputs:10
console.log(obj2.output.apply(obj));
五、callback函数內的this指向调用该callback的函数的this所指向的对象
//<inputtype="text"value="3"id="txt_username">
$("#username").on("click",function(){
 console.log(this.value);
});
六、Function.prototype.bind中的this
Thebind()methodcreatesanewfunctionthat,whencalled,hasitsthiskeywordsettotheprovidedvalue,withagivensequenceofargumentsprecedinganyprovidedwhenthenewfunctioniscalled.
实例一:
functionperson(){
 returnthis.name;
}
//Function.prototype.bind
varper=person.bind({
 name:"zuojj"
});
console.log(per);
varobj={
 name:"Ben",
 person:person,
 per:per
};
//Outputs:Ben,zuojj
console.log(obj.person(),obj.per());
实例二:
this.x=9;
varmodule={
 x:81,
 getX:function(){returnthis.x;}
};
//Outputs:81
console.log(module.getX());
vargetX=module.getX;
//Outputs:9,becauseinthiscase,"this"referstotheglobalobject
console.log(getX);
//createanewfunctionwith'this'boundtomodule
varboundGetX=getX.bind(module);
//Outputs:81
console.log(boundGetX());
