说了你可能不信,其实JS中的this是鳝变的!!!
- this的调用上下文是在执行的时候才确定的,而不是在函数定义的时候确定的。它和变量不同。当然this确实也不是一个变量。
- 如果将this理解成:“函数中的this一般都指向所在的对象” 是错误的。这句话其实把this理解成是静态的。
- 然而this是动态的,实际函数作为方法调用的时候this最终指向的是那个调用它的对象。这句话其实很也迷幻,注意我没有说他是错的,说的是迷幻,所以要进行区分,为什么说是迷幻???。其实在使用箭头函数的时候,对于箭头函数没有this的情况(你要知道箭头函数没有this,但是没有说不给他使用this啊),箭头函数中的this其实可以理解为是静态的,使用指向声明时候的词法作用域。咦,变量不是也是这样的吗?不是吧,不是吧,难道真的是鳝变的吗?
this是什么?
- this不是变量,不是属性名,this是一个关键字。
- JS不允许对this进行赋值。
- this是对象的引用.
this注意点
- this与变量不同,this没有作用域的限制
- 嵌套函数的this
- 嵌套函数作为方法调用,其this的值指向调用它的对象
- 嵌套函数不会从调用它的函数中继承this,嵌套函数作为函数调用this不是全局对象(非严格模式)就是undefined(严格模式)
this的默认绑定
你在看这个点的时候你可能要注意我这三个用词,普通函数,嵌套函数,箭头函数,这三种情况其实导致你晕头转向罪魁祸首
总的来说普通函数和嵌套函数
作为函数调用的时候,不是指向全局对象就是undefined。
值得注意的如果嵌套函数作为函数调用的时候,很多时候会误认为会指向外层函数的上下文。其实嵌套函数不会从调用它的函数中继承this。
嵌套函数的this不是指向全局对象,就是undefined。不仅仅是嵌套函数的this,普通函数也是一样。箭头函数我们可能要另外进行讨论了
案例1:这个案例只是想表达,普通函数作为函数进行调用的时候this的指向问题。
//声明一个函数,他的this默认绑定的是全局对象
function fun1(){
console.log("非严格模式函数中的this:",this)
}
fun1()
运行结果:
案例1:这个案例只是想表达,与案例1相似,主要想看严格模式下普通函数的this的指向问题。
//声明一个函数,在严格模式下,this是undefined
function fun2(){
"use strict"
console.log("严格模式函数中的this:",this)
}
fun2()
运行结果:
案例3:这个案例主要想阐述,嵌套函数作为函数的调用方式是如何的。
//obj中方法fun的嵌套函数fun1,你以为会指向外层函数中的obj.No,他不会。
obj = {
fun : function (){
console.log("obj方法中的this:",this)//
function fun1(){
console.log("obj中方法中的嵌套函数的this:",this)//嵌套函数中的this
console.log(this == window)
}
fun1()
}
}
obj.fun()
运行结果:
案例4:这个案例和案例3类似,案例4主要想看嵌套函数如果是严格模式会是什么情况。
obj = {
fun : function (){
console.log("obj方法中的this:",this)//
function fun1(){
"use strict"
console.log("obj中方法中的嵌套函数(严格模式)的this:",this)//嵌套函数中的this
console.log(this == undefined)
}
fun1()
}
}
obj.fun()
运行结果:
总结:嵌套函数fun1不会从调用它的fun继承this,即使fun的this指向的是obj。
特别的,这里的fun1不会指向他的外层函数的上下文。很多时候你可能会认为fun1中输出的this是obj。
这里只需要记住一点,普通函数和嵌套函数作为`函数调用`,this不是指向全局对象就是undefined。
案例5:这里要来讨论箭头函数的情况了!!!。
你要知道,箭头函数是没有this。普通函数和嵌套函数他们是有this的只不过严格模式下如果他作为函数方式进行调
用this指向的undefined非严格模式下this指向的是全局对象。如果此一来,既然箭头函数都没有this那根本就不用考虑他的动态绑定,它跟变量差不多,自己没有就往上层作用域进行查找嘛。
let a = () => {
console.log(this)
}
let obj4 = {
name:"wangwu",
showThis(){
let fun1 = ()=>{
console.log("fun1中的this:",this)
let fun2 = () =>{
console.log("fun2中的this:",this)
}
fun2()
}
fun1()
}
}
obj4.showThis()
运行结果:
案例5:这里想讨论下如果箭头函数被当成方法的方式调用呢?并且调用对象是别的对象的话。
这里可以很明显的展示出箭头函数跟变量的是作用域是一样的,他是静态的,受到了词法作用域的限制(也就是说this的指向跟定义的时候所处的词法作用域有关),不管谁调用它,它始终是静态的指向定义时的作用域。
let obj5 = {
name:"wangwu",
showThis:function (){
console.log("showThis:",this)
let arrows = ()=>{
console.log("arrows:",this)
}
return arrows//我们将箭头函数作为返回值返回
}
}
let obj6 = {
name:"zhaoliu"
}
obj6.showThis = obj5.showThis()//此时obj6的showThis方法是obj5的arrows箭头函数
console.log("通过obj6进行调用obj5中定义的函数showThis")
obj6.showThis()
运行结果:
不信你可以将箭头函数改为普通的函数,此时this却动态的绑定到obj6上了
let obj5 = {
name:"wangwu",
showThis:function (){
console.log("showThis:",this)
let arrows =function (){//这里命名并非箭头函数为了对比上诉的箭头函数而修改此行代码!!!!!
console.log("arrows:",this)
}
return arrows
}
}
let obj6 = {
name:"zhaoliu"
}
obj6.showThis = obj5.showThis()
console.log("通过obj6进行调用obj5中定义的函数showThis")
obj6.showThis()
运行结果:
this的隐式绑定
作为方法调用的时候,是隐式绑定,隐式的指向调用这个方法的对象。而作为函数调用的时候是默认绑定,默认绑定到全局对象(非严格模式下)。
//定义一个对象obj1,且对象包含一个showThis方法。
let obj1 = {
name:"zhansgan",
showThis:function (){
console.log(this)
}
}
console.log("方法的方式调用:")
obj1.showThis()
let fun = obj1.showThis
console.log("函数的方式调用:")
fun()
运行结果:
这里再次证明作为方法调用的时候this指向的是调用它的对象。
let obj1 = {
name:"zhansgan",
showThis:function (){
console.log(this)
}
}
let obj2 = {
name:"lisi",
}
console.log("将obj1的方法showThis作为obj2的方法,通过obj2再次调用")
obj2.showThis = obj1.shwoThis
obj2.showThis()
console.log("=================================")
运行结果:
this的显示绑定
通过bind
通过call
通过apply
正在梳理…