笼统来说
this指向当前对象,存在于全局对象与函数中
-
在全局环境下this指向的就是全局对象
console.log(this)//Window
-
在函数中,this指向的是调用该函数的对象
function fn(){ console.log(this) } fn()//Window let a={fn:fn} a.fn()//a
改变该规则的行为
- 使用严格模式“use strict”
严格模式下无法再意外创建全局变量,所以所有在全局中定义的函数的this与全局对象解绑,this指向undefined
"use strict"
function fn(){
console.log(this)
}
fn()//undefined
但这么解释或许并不是正确的,严格模式下要求函数必须有确定的调用对象,如a.fn(),所以window.fn()便能得到预期的结果,应该说严格模式只是取消了全局环境下的这一默认行为
"use strict"
function fn(){
console.log(this)
}
window.fn()//Window
- 使用call,apply,bind命令式的强制锁定函数的this指向
使用 call与apply返回的都是一个立即执行函数,是一个新的函数
let a={}
function fn(){
console.log(this)
}
fn.call(a)//a
bind返回的是改变this指向后的这个新的函数,而不是立即执行,需要注意的是改变this指向后的这个新函数是无法再次修改this指向的
let a={}
function fn(){
console.log(this)
}
let b=fn.bind(a)
b.call(window)//a
new 关键字也会改变this指向,但本质其实就是call,new会创建一个新对象,然后让函数内部的this指向这个新对象,具体请了解new关键字的实现
特殊情况下的this
- 箭头函数的this指向
箭头函数没有this, 也可以理解为箭头函数中的this会继承定义函数时的上下文,可以理解为和外层函数指向同一个this
以我的理解,函数存在作用域,这个函数作用于哪一个对象,那么这个函数作用域里的this就指向这个对象,对于箭头函数来说,他没有自己独立的作用域,他的作用域就是包含他的函数的作用域,如果没有这个函数那么作用域就是全局
箭头函数也是无法主动修改this指向的
let a=()=>console.log(this)
a()//Window
let b={a:()=>console.log(this)}
b.a()//Window
let c={a:function(){return ()=>console.log(this)}}
c.a()()//c
a.call(b)//Window
- 异步情况下的this指向
下面一段代码中,b.a()中函数a的this指向对象b,但在setInterval的回调函数里this指向Window。那么将回调函数改为箭头函数,发现this指向了对象b,这段代码的本质其实就是每0.5秒调用一次回调函数,若是当做立即执行函数来解释,那么this指向Window就完全说的通,箭头函数下this指向应与setInterval函数相同,但setInterval是立即执行函数,所以应与a()相同。总结而言可以说此种状况下的this指向完全符合原则并不是什么特殊情况
function a()
{
setInterval(() => {
console.log(this)
}, 500);
}
let b={a}
b.a()//b
function a()
{
setInterval(function(){console.log(this)}, 500);
}
let b={a}
b.a()//Window
实际上setTimeout与setInterval的this实现过程如下
function a(){
(function(){//此处可省略
return function(){console.log(this)}
})()//此处可省略
()
}
let b={a}
b.a()//Window
于是省略后的代码便是熟悉的代码了
let a=new Promise(
function(res){
console.log(this)//Window
res()
}
).then(function(){console.log(this)})//Window
在promise中,不管是不是箭头函数,this指向都是Window。实际上,promise只是将一些函数延后调用罢了,函数调用时作用于谁那this就指向谁
在ajax中,我们需要监听请求的状态,在监听的事件函数里不要用this而直接使用xhr对象,防止浏览器在处理时出错
-
立即执行函数的this指向
let a=function(){ return function(){console.log(this)} } let b={a} b.a()()//window let a=function(){ return function(){console.log(this)}() } let b={a} b.a()//window
好似没有什么不同,若是以后有什么需要补充的地方再来补充