箭头函数和普通函数中this的区别

14 阅读2分钟

在 TypeScript 中,普通函数和箭头函数在 this 的指向方面存在显著区别,下面为你详细介绍。

普通函数中的 this

在普通函数里,this 的指向是根据函数的调用方式动态确定的,它可以指向不同的对象,具体情况如下:

1. 全局作用域中调用

当在全局作用域中调用普通函数时,this 指向全局对象(在浏览器环境中是 window 对象,在 Node.js 环境中是 global 对象)。

function globalThisExample() {
    console.log(this);
}
globalThisExample(); 
// 在浏览器环境中,输出: Window 对象

2. 作为对象的方法调用

当普通函数作为对象的方法调用时,this 指向调用该方法的对象。

const person = {
    name: 'John',
    sayHello: function() {
        console.log(`Hello, my name is ${this.name}`);
    }
};
person.sayHello(); 
// 输出: Hello, my name is John

3. 作为构造函数调用

当使用 new 关键字调用普通函数作为构造函数时,this 指向新创建的对象。

function Person(name) {
    this.name = name;
    this.sayHello = function() {
        console.log(`Hello, my name is ${this.name}`);
    };
}
const newPerson = new Person('Jane');
newPerson.sayHello(); 
// 输出: Hello, my name is Jane

4. 使用 callapplybind 方法调用

可以使用 callapplybind 方法显式地指定 this 的指向。

function greet(message) {
    console.log(`${message}, my name is ${this.name}`);
}
const person1 = { name: 'Alice' };
greet.call(person1, 'Hi'); 
// 输出: Hi, my name is Alice

箭头函数中的 this

箭头函数没有自己的 this,它的 this 继承自外层函数或全局作用域,也就是在定义箭头函数时所在的上下文。

1. 全局作用域中定义的箭头函数

在全局作用域中定义的箭头函数,this 指向全局对象。

const globalArrowThis = () => {
    console.log(this);
};
globalArrowThis(); 
// 在浏览器环境中,输出: Window 对象

2. 作为对象的方法使用箭头函数

当箭头函数作为对象的方法时,this 不会指向该对象,而是继承自外层作用域。

const person2 = {
    name: 'Bob',
    sayHello: () => {
        console.log(`Hello, my name is ${this.name}`);
    }
};
person2.sayHello(); 
// 输出: Hello, my name is undefined,因为 this 指向全局对象,全局对象上没有 name 属性

3. 解决回调函数中 this 指向问题

箭头函数常用于解决回调函数中 this 指向问题。

class Counter {
    count = 0;
    increment() {
        // 使用箭头函数,this 继承自 increment 方法的上下文
        setInterval(() => {
            this.count++;
            console.log(this.count);
        }, 1000);
    }
}
const counter = new Counter();
counter.increment(); 
// 每秒输出递增的数字

总结

  • 普通函数的 this 指向是动态的,根据函数的调用方式而定。
  • 箭头函数没有自己的 this,它的 this 继承自外层作用域,在定义时就确定了,不会随调用方式改变。因此,箭头函数更适合用于不需要自己的 this 上下文的场景,如回调函数。