阅读 16

()=>this.tick()

()=>this.tick() 是 ES6 中声明函数的一种方式,叫做箭头函数表达式,引入箭头函数有两个方面的作用:更简短的函数并且不绑定 this。

var f = ([参数]) => 表达式(单一)
// 等价于以下写法
var f = function([参数]){
   return 表达式;
}
复制代码

箭头函数的基本语法如下:

(参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一)
//相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }

// 当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}

// 没有参数的函数应该写成一对圆括号。
() => {函数声明}
复制代码

根据以上概念,尝试将 setInterval 中调用 tick() 的方式改为通常声明方式:

this.timerID = setInterval(function(){
    return this.tick();
  },1000
);
复制代码

但是会报错,tick() 不是一个方法。

2、this.tick()

this.tick() 中的 this 指代的是 function,而不是我们想要的指代所在的组件类 Clock,所以我们要想办法让 this 能被正常指代。这里我们采用围魏救赵的办法:

let that = this;
this.timerID = setInterval(function () {
  return that.tick();
},1000);
复制代码

在闭包函数的外部先用 that 引用组件 Clock 中挂载组件方法 componentDidMount() 中 this 的值,然后在 setInterval 中闭包函数中使用that,that 无法找到声明,就会根据作用域链去上级(上次层)中继承 that,也就是我们引用的组件类 Clock 中的 this。

到此为止,将 () => this.tick()等价代换为了我们熟悉的形式。

所列举将箭头函数用法恢复成常规写法,报错:tick() 不是一个方法的原因在于 setInterval 是 window 的方法,内闭包使用 this 当然也指向 window,window 没有 tick() 方法故报错。

this.timerID = setInterval(function(){   //setInterval是window的方法
    return this.tick();                  //this指的是window
  },1000
);
复制代码

所以需要更改指向,在 setInterval 外部定义变量,let that/_this = this,才能正常使用 _this.tick()。

componentDidMount(){
    let _this = this;
    this.timerID = setInterval(function(){
      _this.tick();
    }, 1000);
}
复制代码