您好,欢迎访问一九零五行业门户网

javascript中this关键字的用法(附代码)

本篇文章给大家带来的内容是关于利用javascript中this关键字的用法(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本文主要解释在js里面this关键字的指向问题(在浏览器环境下)。
首先,必须搞清楚在js里面,函数的几种调用方式:
普通函数调用
作为方法来调用
作为构造函数来调用
使用apply/call方法来调用
function.prototype.bind方法
es6箭头函数
但是不管函数是按哪种方法来调用的,请记住一点:谁调用这个函数或方法,this关键字就指向谁。
接下来就分情况来讨论下这些不同的情况:
1、普通函数调用function person(){ this.name="xl"; console.log(this); console.log(this.name); } person(); //输出 window xl
在这段代码中person函数作为普通函数调用,实际上person是作为全局对象window的一个方法来进行调用的,即window.person();
所以这个地方是window对象调用了person方法,那么person函数当中的this即指window,同时window还拥有了另外一个属性name,值为xl.
var name="xl"; function person(){ console.log(this.name); } person(); //输出 xl
同样这个地方person作为window的方法来调用,在代码的一开始定义了一个全局变量name,值为xl,它相当于window的一个属性,即window.name="xl",又因为在调用person的时候this是指向window的,因此这里会输出xl.
2、作为方法来调用在上面的代码中,普通函数的调用即是作为window对象的方法进行调用。显然this关键字指向了window对象。
再来看下其他的形式
var name="xl"; var person={ name:"xl", showname:function(){ console.log(this.name); } } person.showname(); //输出 xl //这里是person对象调用showname方法,很显然this关键字是指向person对象的,所以会输出name var shownamea=person.showname; shownamea(); //输出 xl //这里将person.showname方法赋给shownamea变量,此时shownamea变量相当于window对象的一个属性,因此shownamea()执行的时候相当于window.shownamea(),即window对象调用shownamea这个方法,所以this关键字指向window
再换种形式:
var persona={ name:"xl", showname:function(){ console.log(this.name); } } var personb={ name:"xl", sayname:persona.showname } personb.sayname(); //输出 xl //虽然showname方法是在persona这个对象中定义,但是调用的时候却是在personb这个对象中调用,因此this对象指向personb
3、作为构造函数来调用function person(name){ this.name=name; } var persona=person("xl"); console.log(persona.name); // 输出 undefined console.log(window.name);//输出 xl //上面代码没有进行new操作,相当于window对象调用person("xl")方法,那么this指向window对象,并进行赋值操作window.name="xl". var personb=new person("xl"); console.log(personb.name);// 输出 xl //这部分代码的解释见下
new操作符//下面这段代码模拟了new操作符(实例化对象)的内部过程 function person(name){ var o={};//创建空对象 o.__proto__=person.prototype; //为创建对象指定原型,继承原型属性和方法 person.call(o,name); return o; } var personb=person("xl"); console.log(personb.name); // 输出 xl
这段代码涉及到了_proto_及prototype的概念,如果有需要了解,请点击链接
在person里面首先创建一个空对象o,将o的proto指向person.prototype完成对原型的属性和方法的继承
person.call(o,name)这里即函数person作为apply/call调用(具体内容下方),将person对象里的this改为o,即完成了o.name=name操作
返回对象o。
因此`person("xl")`返回了一个继承了`person.prototype`对象上的属性和方法,以及拥有`name`属性为"xl"的对象,并将它赋给变量`personb`. 所以`console.log(personb.name)`会输出"xl"
4、call/apply方法的调用在js里函数也是对象,因此函数也有方法。从function.prototype上继承到function.prototype.call/function.prototype.apply方法
call/apply方法最大的作用就是能改变this关键字的指向。
obj.method.apply(anotherobj,arguments);
var name="xl"; var person={ name:"xl", showname:function(){ console.log(this.name); } } person.showname.call(); //输出 "xl" //这里call方法里面的第一个参数为空,默认指向window。 //虽然showname方法定义在person对象里面,但是使用call方法后,将showname方法里面的this指向了window。因此最后会输出"xl"; funtion fruita(n1,n2){ this.n1=n1; this.n2=n2; this.change=function(x,y){ this.n1=x; this.n2=y; } } var fruita=new fruita("cheery","banana"); var fruitb={ n1:"apple", n2:"orange" }; fruita.change.call(fruitb,"pear","peach"); console.log(fruitb.n1); //输出 pear console.log(fruitb.n2);// 输出 peach
fruitb调用fruita的change方法,将fruita中的this绑定到对象fruitb上。
5、function.prototype.bind()方法var name="xl"; function person(name){ this.name=name; this.sayname=function(){ settimeout(function(){ console.log("my name is "+this.name); },50) } } var person=new person("xl"); person.sayname() //输出 “my name is xl”; //这里的settimeout()定时函数,相当于window.settimeout(),由window这个全局对象对调用,因此this的指向为window,则this.name则为xl
那么如何才能输出"my name is xl"呢?
var name="xl"; function person(name){ this.name=name; this.sayname=function(){ settimeout(function(){ console.log("my name is "+this.name); }.bind(this),50) //注意这个地方使用的bind()方法,绑定settimeout里面的匿名函数的this一直指向person对象 } } var person=new person("xl"); person.sayname(); //输出 “my name is xl”;
这里settimeout(function(){console.log(this.name)}.bind(this),50);匿名函数使用bind(this)方法后创建了新的函数,这个新的函数不管在什么地方执行,this都指向的person,而非window,因此最后的输出为"my name is xl"而不是"my name is xl"
另外几个需要注意的地方:
settimeout/setinterval/匿名函数执行的时候,this默认指向window对象,除非手动改变this的指向。在《javascript高级程序设计》当中,写到:“超时调用的代码(settimeout)都是在全局作用域中执行的,因此函数中的this的值,在非严格模式下是指向window对象,在严格模式下是指向undefined”。本文都是在非严格模式下的情况。
var name="xl"; function person(){ this.name="xl"; this.showname=function(){ console.log(this.name); } settimeout(this.showname,50); } var person=new person(); //输出 "xl" //在settimeout(this.showname,50)语句中,会延时执行this.showname方法 //this.showname方法即构造函数person()里面定义的方法。50ms后,执行this.showname方法,this.showname里面的this此时便指向了window对象。则会输出"xl";
修改上面的代码:var name="xl"; function person(){ this.name="xl"; var that=this; this.showname=function(){ console.log(that.name); } settimeout(this.showname,50) } var person=new person(); //输出 "xl"13 //这里在person函数当中将this赋值给that,即让that保存person对象,因此在settimeout(this.showname,50)执行过程当中,console.log(that.name)即会输出person对象的属性"xl"
匿名函数:var name="xl"; var person={ name:"xl", showname:function(){ console.log(this.name); } sayname:function(){ (function(callback){ callback(); })(this.showname) } } person.sayname(); //输出 xl var name="xl"; var person={ name:"xl", showname:function(){ console.log(this.name); } sayname:function(){ var that=this; (function(callback){ callback(); })(that.showname) } } person.sayname() ; //输出 "xl" //匿名函数的执行同样在默认情况下this是指向window的,除非手动改变this的绑定对象
6、eval函数eval函数执行的时候,this绑定到当前作用域的对象上。
var name="xl"; var person={ name:"xl", showname:function(){ eval("console.log(this.name)"); } } person.showname(); //输出 "xl" var a=person.showname; a(); //输出 "xl"
7、箭头函数es6里面this指向固定化,始终指向外部对象,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向。
function timer() { this.seconds = 0; setinterval( () => this.seconds ++, 1000); } var timer = new timer(); settimeout( () => console.log(timer.seconds), 3100); // 3 // 在构造函数内部的setinterval()内的回调函数,this始终指向实例化的对象,并获取实例化对象的seconds的属性,每1s这个属性的值都会增加1。否则最后在3s后执行settimeout()函数执行后输出的是0
相关文章推荐:
vuex模块化和命名空间的实例代码
vue组件是什么?vue组件的的介绍
js如何获取文件上传进度?js获取文件上传进度的代码
以上就是javascript中this关键字的用法(附代码)的详细内容。
其它类似信息

推荐信息