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());