背景:
this是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象(this到底指向哪个对象必须到函数被调用时才能确定)。
在实际开发中,this的指向可以通过不同的调用模式来判断:
- 函数调用模式:当一个函数不是一个对象的方法,直接作为函数来调用时,非严格模式this指向window对象,严格模式this是undefined。
- 方法调用模式:当一个函数作为一个对象的方法来调用时,this指向这个对象。
- 构造器调用模式:当一个函数用new调用时,函数执行前会新创建一个对象,this指向这个新创建的对象。
- apply()方法、call()方法和bind()方法调用模式:可以指定调用函数时函数内部的this指向。
当没有传入参数、传入参数是undefined、传入参数是null,this指向window对象。
这四种方式中,使用构造器调用模式的优先级最高,然后是apply()方法、call()方法和bind()方法调用模式,再然后是方法调用模式,最后是函数调用模式。
拓展:
- 定时器+function,this指向window对象。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// this指向window对象
function fn() {
setTimeout(function () {
console.log(this);
}, 1000);
}
fn.call({x: 100});
// this指向window对象
const a = {
fn() {
setTimeout(function () {
console.log(this);
}, 1000);
}
}
a.fn();
</script>
</html>
- 定时器+箭头函数,this是上层作用域的this。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// this指向{x: 100}
function fn() {
setTimeout(() => {
console.log(this);
}, 1000);
}
fn.call({x: 100});
// this指向fn
const a = {
fn() {
setTimeout(() => {
console.log(this);
}, 1000);
}
}
a.fn();
</script>
</html>
- 由于箭头函数根本没有自己的this,导致函数内部的this就是外层代码块的this,即指向外层函数中的this。(即箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。)
- 有function作用域,this是上层作用域的this。
- 没有function作用域,this指向window对象。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
// this指向Obj
class Obj {
say = () => {
console.log(this);
}
};
// new了就代表有function作用域
const obj1 = new Obj();
obj1.say();
// this指向window对象
const obj2 = {
say: () => {
console.log(this);
}
};
obj2.say();
</script>
</html>