() => this.tick(),这里为什么不能改为this.tick()?谢谢

#1
class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { seconds: 0 };
  }

  tick() {
    this.setState(prevState => ({
      seconds: prevState.seconds + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
      <div>
        Seconds: {this.state.seconds}
      </div>
    );
  }
}

ReactDOM.render(<Timer />, mountNode);
#2

使用箭头函数不会改变函数内this指向

#3

() => this.tick()
可以改为
this.tick

#4

使用React.component这种方法生成一个组件Timer的时候,用React的方式绑定事件处理函数,事件处理函数并没有绑定在当前组件Timer上的, 因此我们要这么写:

  此时handleClick方法里面的this.setState中的this才是指向当前组件。

同理的,我们知道setInterval的里面的回调函数中的this是指向windows对象的,直接写this.tick()肯定是不对的。而使用箭头函数的方式,首先箭头函数是没有自己的this的,箭头函数里面的this是定义时所在对象,即Timer组件,由于绑定在了当前组件,所以方法的调用和方法的执行,其中的this都正确的指向组件。
另外,绑定事件也可以这么写:

 { this.handleClick() } }>

个人理解,不喜勿喷:joy:

#5

感谢,非常经典

#6

应该setInterval使用箭头函数能够使用this,但是tick中得作用域是window 所以你再绑定tick方法时候必须要使用箭头函数,或者bind给函数绑定this

#7

setInterval 中直接使用this.tick(), 首先这个this指向明显不对啊。要不你用个bind绑定下试试。

#8

明显this指向不对,一个指向window,一个是指向本组件。

#9

先来看个this指向问题的栗子:chestnut:

var obj = {
 hello(){
   console.log( this ) 
 }
}

obj.hello()  // this === obj

var refHello = obj.hello()

refHello()  // this === window

先确保能看懂,如果不清楚this指向的问题,可以先移步:this 的工作原理。理解清楚了,往下看。


回到你的问题:

/* 
** 当this.tick() 执行的时候
** 函数体中的this会去找当前是谁执行这个函数的,本例是.tick()符号点的前面的那个对象,也就是this
** 而this等于componentDidMount中的this(箭头函数不改变this,向上找),也就是当前component实例
** 所以this能查找正确
*/
this.interval = setInterval(() => this.tick(), 1000); 



// 如果改成如下
this.interval = setInterval(  this.tick , 1000);
// 相当于如下
var anonyFunc = this.tick
this.interval = setInterval(  anonyFunc , 1000);
/*
** 当一秒钟之后,执行的就是anonyFunc()
** anonyFunc函数体会去查找this,发现是函数调用(anonyFunc()),而不是对象的方法调用
** 那这里的this指向就是全局对象了,也就是window
*/

看到这里,你应该能清楚为什么不能了。

不过,既然说到这了,我就在展开一下。react官方推荐的在构造方法里面通过bind绑定的方式:

class A extends React.Component {
  constructor( props ) {
    super( props )
    this.methodXXX = this.methodXXX.bind( this )
  }
  methodXXX(){
     // do some thing
  }
  render(){
    return <div onClick={ this.methodXXX }></div>
  }
}

render中的onClick={ this.methodXXX },其实jsx翻译之后,类似于:

var clickFunc = this.methodXXX
var div = document.querySelector('div')
div.addEventListener( 'click' , clickFunc  )

后续click事件发生其实就是函数调用了,但是因为事先在constructor构造函数中通过bind绑定过了this,所以虽然是函数调用但是也能成功找到预期的this。

每次显式的写这种bind方法,是一件痛苦的事情,好在有个提案:ES proposal: class fields

能让我们这么写:

class A extends React.Component {
  constructor( props ) {
    super( props )
  }
  methodXXX = () => {
     // do some thing
  }
  render(){
    return <div onClick={ this.methodXXX }></div>
  }
}

利用箭头函数,帮我们隐式绑定了this,可以愉快的赋值了,妈妈再也不怕我弄丢this了。这个写法react官方也有提及:Class Properties

以上,all

递归渲染,加了bind(this)函数后好了?