【js】箭头函数和普通函数在this指向的区别

在JavaScript中,箭头函数(Arrow Functions)和普通函数(Function Declarations/Expressions)在this的指向上有显著的不同:

普通函数:

  • 函数定义时this的值在函数被调用时才会确定,它取决于函数是如何被调用的。
  • 独立调用:如果函数是直接调用的(而不是作为对象的方法),在非严格模式下this指向全局对象(在浏览器中通常是window),在严格模式下thisundefined
  • 作为对象方法调用:如果函数作为对象的方法被调用,this指向该对象。
  • 构造函数调用:如果函数前面有new关键字,this指向新创建的对象。
  • callapplybind方法:可以使用这些方法显式地设置函数调用时this的值。

箭头函数:

  • 没有自己的this:箭头函数不绑定自己的this,它会捕获其所在上下文的this值作为自己的this值。
  • 定义时的上下文this的值在箭头函数创建时就已经确定了,它继承自外围作用域。
  • 不可改变:由于箭头函数的this是继承来的,所以使用callapplybind方法也不能改变this的值。
  • 不能用作构造函数:箭头函数没有[[Construct]]方法,因此不能用作构造函数来使用new关键字。

示例比较:

普通函数:
function Person() {
  this.age = 0;
  setInterval(function growUp() {
    // 在非严格模式下,这里的`this`指向全局对象,而不是Person实例
    this.age++;
  }, 1000);
}
var p = new Person();
箭头函数:
function Person() {
  this.age = 0;
  setInterval(() => {
    // 这里的`this`正确地指向Person实例
    this.age++;
  }, 1000);
}
var p = new Person();

在第一个例子中,growUp函数是一个普通函数,在setInterval回调中它的this不会指向Person实例,而是指向全局对象或undefined(取决于是否为严格模式)。在第二个例子中,箭头函数在Person的上下文中创建,所以它的this指向Person实例。

因此,箭头函数在处理this时提供了更简洁和可预测的行为,特别是在事件处理和回调函数中,它们避免了this指向错误的问题。然而,这也意味着箭头函数不能用作对象方法,特别是那些需要有自己的this上下文的方法。

当函数作为对象的方法被调用时,this关键字通常指向调用该方法的对象。以下是一些具体情况:

普通函数作为对象方法:

const obj = {
  myMethod: function() {
    // 这里的`this`指向`obj`对象
    console.log(this);
  }
};
obj.myMethod(); // 输出:obj

在上面的例子中,当myMethod被调用时,this指向obj对象。

箭头函数作为对象方法:

const obj = {
  myMethod: () => {
    // 这里的`this`不会指向`obj`对象
    // 而是继承自外围作用域的`this`
    console.log(this);
  }
};
obj.myMethod(); // 输出:Window(或全局对象,取决于调用环境)

在这个例子中,箭头函数myMethod中的this不会指向obj对象,而是继承了它定义时的外围作用域的this值。如果在全局作用域中定义箭头函数,那么this通常指向全局对象(在浏览器中通常是Window)。

注意事项:

  • 如果在严格模式下执行代码,普通函数中的this如果是独立调用的(不是作为对象的方法),则this会是undefined,而不是全局对象。
  • 如果使用了callapplybind方法来调用函数,this的值将被显式设置,无论函数是普通函数还是箭头函数(尽管对箭头函数来说,bind不会起作用,因为箭头函数的this不能被改变)。

因此,当函数作为对象的方法调用时,普通函数的this指向调用它的对象,而箭头函数的this指向它定义时的外围作用域的this值。

### JavaScript箭头函数普通函数 `this` 指向差异 #### 普通函数中的 `this` 在普通函数中,`this` 的值取决于函数如何被调用。当一个函数作为对象的方法被调用时,该方法内的 `this` 将指向调用它的那个对象[^1]。 如果是在全局环境中执行,则 `this` 会指向全局对象,在浏览器环境下通常是 `window` 对象;而在严格模式下则为 `undefined`[^4]。 ```javascript function greet() { console.log(this); } greet(); // 如果不在严格模式下, 输出 Window {...} ``` #### 箭头函数中的 `this` 相比之下,箭头函数并没有自己的 `this` 绑定。相反,它们继承自外部最近一层非箭头函数的作用域链上的 `this` 值,即所谓的词法作用域行为。 这意味着即使在一个对象内部定义了一个箭头函数并尝试通过该对象访问属性或方法,箭头函数里的 `this` 还是指向外层作用域而非当前对象实例: ```javascript const obj = { name: 'Object', regularFunc: function () { console.log('Regular:', this.name); const arrowFunc = () => { console.log('Arrow:', this.name); }; arrowFunc(); } }; obj.regularFunc(); // Regular: Object // Arrow: Object ``` 上述例子展示了两种类型的函数对于相同上下文的不同表现形式——普通函数能够正确获取到所属对象的信息,而箭头函数则是基于其创建位置所处的环境来决定 `this` 的具体含义。 #### 实际应用场景对比 考虑到这一点,在某些情况下选择合适的函数类型非常重要。例如,在事件监听器或者定时器回调里使用普通函数可以确保每次触发都能获得最新的 DOM 节点状态;而对于那些不需要独立 `this` 上下文的任务来说,采用更简洁明了的箭头表达式可能是更好的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值