- 以下讨论情况针对浏览器宿主环境
- 情况一: 函数调用时候前面没有调用者,也就是
fn()
前面没有点
,那么非严格模式下this就是window
严格模式下this就是undefined
// 注意:let/const没有和全局对象window映射关系
// 非严格模式
const foo1 = function () {
console.log(this)
}
foo1() // this:window 函数调用前面没有`.`
const obj = {
bar () {
console.log(this)
}
}
let foo2 = obj.bar
foo2() // this:window 函数调用前面没有'.'
const foo3 = function (fn) {
fn() // this:window 函数调用前面没有'.'
}
foo3(obj.bar)
// 严格模式
"use strict"
const foo1 = function () {
console.log(this)
}
foo1() // this:undefined
const obj = {
bar () {
console.log(this)
}
}
let foo2 = obj.bar
foo2() // this:undefined
const foo3 = function (fn) {
fn() // this:undefined
}
foo3(obj.bar)
结果
- 情况二:函数调用时候前面拥有
点
,那么点
前面那个称为调用者
。函数调用栈内部this
就是调用者
const obj = {
bar () {
console.log(this)
}
}
obj.bar() // this:obj; bar函数调用时候'.'前面就是obj,那么bar函数内部this就是obj
<style>
.box {
width: 100px;
height: 100px;
background-color: #fa0;
}
</style>
<div class="box"></div>
const boxEle = document.querySelector('.box')
boxEle.addEventListener('click',function () {
console.log(this) // this:boxEle
})
boxEle.onclick = function () {
consoele.log(this) // this:boxEle
}
- 情况三:构造器内部this指向当前实例
function Person() {
console.log(this)
}
class Page {
constructor () {
console.log(this)
}
}
new Person() // this:Person实例
new Page() // this:Page实例
- 其他情况
1)浏览器定时器回调函数调用栈内部this非严格模式window
,严格模式undefined
2)自执行函数调用栈内部this非严格模式window
,严格模式undefined
3)数组内置方法回调处理函数调用栈内部this一般情况
指向window
4)间接调用类似自执行函数
// 定时器
setTimeout(function () {
console.log(this) // 非严格模式this:window
},2000)
// 数组API回调
;[1,2].forEach(function (item){
console.log(this) // this:windnow
})
// 自执行函数
;(function () {
console.log(this) // 非严格模式自调用函数内部this:window
})()
const obj1 = {
foo () {
console.log(this)
}
}
const obj2 = {
bar () {
console.log(this)
}
}
// 间接调用
;(obj2.bar = obj1.foo)() // this:window
- 情况四:
call、apply、bind
可以修改ES3/ES5规范函数的this指向
function bar() {
console.log(this)
}
const obj = {
name:'obj',
foo () {
console.log(this)
}
}
bar.call(obj) // this:obj
obj.foo.call(null) // this:window
obj.foo.call() // this:window
- 情况五:箭头函数
1)箭头函数调用栈内部this永远取决于上级作用域
,和调用者没有任何关系。JavaScript语言中对象的{}
不是调用栈,不会形成作用域,仅仅是一个命名空间
,没有this。JavaScript编程语言中,只有全局作用域、局部作用域
以及ES6新规范的块级作用域
function bar () {
console.log('window bar')
}
const obj = {
foo: () => {
console.log(this) // this:window 。对象的{}不会形成作用域,此时箭头函数foo上级作用域就是全局作用域window
this.bar() // 'window bar'
},
bar () {
console.log(this) // this:obj
// baz的上级作用域是bar函数调用栈 所以箭头函数baz内部this:obj
const baz = () => {
console.log('obj bar') // this:obj
}
baz()
}
}
obj.foo()
obj.bar()