帮我解释下这个s2为什么是0,为什么值没有变化,谢谢大佬们

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

上面代码中,Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(即Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1被更新了 3 次,而timer.s2一次都没更新。
这是阮一峰es6中说的,我也理解s2的this指向window对象,但是不理解为什么值是0,而没有变化,

阅读 3.2k
4 个回答

箭头函数,this的作用域跟父函数一致,所以setInterval(() => this.s1++, 1000);的this指向和this.s1 = 0;一致。
非箭头函数的setInterval(function () {this.s2++;}, 1000);的this指向是window,为什么是window?因为这里是一个匿名函数。为什么匿名函数就指向window呢?
这就牵涉到this的作用域问题。
在js中,this这个指向并不是在函数声明的时候确定的,而是函数执行的时候才确定的,谁调用了这个方法,这个方法的this就指向谁。
根据var timer = new Timer();timer.s1,我们知道,实例化Timer的是timer,通过timer调用s1,所以this指向timer,这个是没问题的。
但是匿名函数没人调他,根据设定,没人调那就找不到负责人,私生子?只能委托给window,所以匿名函数的this都指向window。
所以setInterval(function () {this.s2++;}, 1000);就相当于setInterval(function () {window.s2++;}, 1000);很显然,timer.s2根本就没动,自然就是0.
这个时候如果你打印window.s2,结果就是NaN,为什么?
window.s2 这个变量并没有声明,那就是undefined,一个undefined的变量自增,就是NaN。

console 出来的 timer.s2 是 timer 实例的属性,又不是 window 下的属性。
初始值设置的 0,当然就是 0了。走点心?

跑一遍:

var s2 = 0;

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('[Timer]s1: ', timer.s1), 3100);
setTimeout(() => console.log('[Timer]s2: ', timer.s2), 3100);
setTimeout(() => console.log('[window]s2: ', window.s2), 3100);

// [Timer]s1:  3
// [Timer]s2:  0
// [window]s2:  3

再不明白真没辙了。。

问题中,你分析的挺好的啊
在构造函数中,第一个定时器里的 this.s1 和 后续的实例 timer.s1 指向了同一个属性。
而,this.s2 中的 this简单等同于window的话,这里执行this.s2++,由于全局没有定义变量,结果应该是 NaN。后续timer.s2指向的是 构造函数中 初始化的 this.s2 = 0,所以就是 0喽

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题