1. 普通函数
普通函数的this指向其调用者。
1.1 独立调用
独立调用的普通和匿名函数this指向全局对象(window/globalThis),因为独立调用本质上还是全局对象调用。
独立调用案例1:
let obj = {
name: "jqm",
foo: function () {
function a() {
console.log("this", this);
}
a(); // 独立调用 this指向全局对象
},
};
obj.foo();复制代码
独立调用案例2:
function foo() {
console.log(this); //window obj.foo在bar函数内独立调用
}
function bar(fn) {
fn();
}
let obj = {
name: "obj",
foo: foo,
};
bar(obj.foo);复制代码
1.2 对象调用方法
通过对象调用普通函数,普通函数的this指向调用者
对象调用方法案例1:
let obj = {
name: "obj",
foo: function () {
console.log(this); //this指向obj
},
};
obj.foo();
复制代码
1.3 显式绑定函数this
js中更改匿名函数this的方法:call、apply、bind。其中bind返回一个新函数,新函数指向绑定的对象,旧函数不会,apply和call直接调用函数,apply和call的区别是,apply第二个参数是数组,call是一个一个的传参。
使用了call、apply或者bind方法调用函数,函数的this指向其第一个参数。
案例:
function a() {
console.log("this", this);
}
a.call({ name: "jqm" });复制代码
1.4 new绑定
函数通过new 实例化后,函数返回的对象中的this指向实例对象。
2. 箭头函数
箭头函数的this固定指向其父级作用域的上下文(只有两种作用域生效:全局作用域和函数作用域,块级作用域不影响this)。
通俗点讲就是:箭头函数的this指向其上层的第一个普通函数的this。
案例:
var a = 0;
function foo() {
let test = () => {
console.log(this);
};
return test;
}
let obj = { a: 1, foo };
const fn = obj.foo();
const obj2 = { name: "obj2", fn };
obj2.fn(); // 输出:obj复制代码
注意:如果箭头函数的父级作用域是函数,那么这个箭头函数的this就指向这个函数的this,所以要注意箭头函数的父级函数的调用者。
显式绑定对箭头函数无效:
var a = 0
function foo() {
let test = () => {
console.log(this)
}
return test
}
let obj1 = {
a: 1,
foo: foo
}
let obj2 = {
a: 2,
foo: foo
}
obj1.foo().call(obj2)
//obj1.foo()返回test obj1.foo.call(obj2)把test的指向绑定到obj2上,无效,this依然指向obj1复制代码