You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
varname="XL";functionPerson(name){this.name=name;this.sayName=function(){setTimeout(function(){console.log("my name is "+this.name);},50)}}varperson=newPerson("xl");person.sayName()//输出 “my name is XL”;//这里的setTimeout()定时函数,相当于window.setTimeout(),由window这个全局对象对调用,因此this的指向为window, 则this.name则为XL
那么如何才能输出"my name is xl"呢?
varname="XL";functionPerson(name){this.name=name;this.sayName=function(){setTimeout(function(){console.log("my name is "+this.name);}.bind(this),50)//注意这个地方使用的bind()方法,绑定setTimeout里面的匿名函数的this一直指向Person对象}}varperson=newPerson("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"
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下)。
首先,必须搞清楚在JS里面,函数的几种调用方式:
但是不管函数是按哪种方法来调用的,请记住一点:谁调用这个函数或方法,this关键字就指向谁。
接下来就分情况来讨论下这些不同的情况:
##普通函数调用
在这段代码中
person
函数作为普通函数调用,实际上person
是作为全局对象window
的一个方法来进行调用的,即window.person()
;所以这个地方是
window
对象调用了person
方法,那么person
函数当中的this
即指window
,同时window
还拥有了另外一个属性name
,值为xl
.同样这个地方
person
作为window
的方法来调用,在代码的一开始定义了一个全局变量name
,值为xl
,它相当于window
的一个属性,即window.name="xl"
,又因为在调用person
的时候this
是指向window
的,因此这里会输出xl
.##作为方法来调用
在上面的代码中,普通函数的调用即是作为
window
对象的方法进行调用。显然this
关键字指向了window
对象.再来看下其他的形式
再换种形式:
##作为构造函数来调用
###new操作符
在
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"##call/apply方法的调用
在JS里函数也是对象,因此函数也有方法。从Function.prototype上继承到
Function.prototype.call/Function.prototype.apply
方法call/apply
方法最大的作用就是能改变this
关键字的指向.Obj.method.apply(AnotherObj,arguments);
FruitB
调用fruitA
的change
方法,将fruitA
中的this
绑定到对象FruitB
上。##Function.prototype.bind()方法
那么如何才能输出
"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”。本文都是在非严格模式下的情况。修改上面的代码:
匿名函数:
##Eval函数
该函数执行的时候,this绑定到当前作用域的对象上
##箭头函数
es6
里面this
指向固定化,始终指向外部对象,因为箭头函数没有this
,因此它自身不能进行new
实例化,同时也不能使用call, apply, bind
等方法来改变this
的指向##参考资料
The text was updated successfully, but these errors were encountered: