this的四种绑定方式
在 JavaScript 中,this 的绑定方式主要有 四种,按照优先级从高到低依次是:
1. new 绑定
当函数通过 new 关键字调用时(即作为构造函数调用),会创建一个新对象,并将 this 绑定到这个新对象上。
function Person(name) {
this.name = name;
}
const p = new Person('Damo');
console.log(p.name); // 'Damo'
此时
this指向新创建的实例对象。
2. 显式绑定
通过 call、apply 或 bind 方法显式地指定 this 的值。
function greet() {
console.log(`Hello, ${this.name}`);
}
const obj = { name: 'Damo' };
greet.call(obj); // Hello, Damo
greet.apply(obj); // Hello, Damo
const boundGreet = greet.bind(obj);
boundGreet(); // Hello, Damo
注意:
bind返回一个新函数,其this被永久绑定(除非使用new调用)。
3. 隐式绑定
当函数作为对象的方法被调用时,this 绑定到该对象。
const obj = {
name: 'Damo',
sayHi() {
console.log(this.name);
}
};
obj.sayHi(); // Damo
⚠️ 注意“隐式丢失”问题:如果将方法赋值给变量或作为回调传入,可能会丢失
this上下文。
const fn = obj.sayHi;
fn(); // undefined(在非严格模式下为全局对象)
4. 默认绑定
当函数独立调用(不带任何上下文)时,this 采用默认绑定:
- 在 非严格模式 下,
this指向全局对象(浏览器中是window,Node.js 中是global)。 - 在 严格模式(
'use strict')下,this为undefined。
function foo() {
console.log(this);
}
foo(); // 非严格模式:window;严格模式:undefined
补充说明:箭头函数
箭头函数 没有自己的 this,它会继承外层作用域的 this 值(词法作用域绑定),因此不受上述四种规则影响。
const obj = {
name: 'Damo',
greet: () => {
console.log(this.name); // this 指向外层(通常是 window 或 undefined)
},
greetNormal() {
const arrow = () => console.log(this.name);
arrow(); // 'Damo',因为箭头函数继承了 greetNormal 的 this
}
};
obj.greet(); // undefined
obj.greetNormal(); // Damo
箭头函数在类中的应用:
class MyClass {
name = 'Damo';
// 箭头函数作为类字段(属性),用于绑定this,this永远指向类的实例
greet = () => {
console.log('Hello, ' + this.name);
};
// ❌ 以下的两种方式是语法错误
() => {
console.log(this.name);
};
myMethod: () => { };
}
优先级总结(从高到低):
- new 绑定
- 显式绑定(
call/apply/bind) - 隐式绑定(对象方法调用)
- 默认绑定(独立函数调用)
箭头函数不参与此规则,它直接使用定义时所在上下文的
this。
思考部分(ps:没事找事部分):
1.new 函数的call,apply和bind方法,有会有什么结果
2.new一个对象的方法和new一个类的方法会发生什么
3.可以给this直接赋值吗?比如:
this = { a: 'Hello' };