针对“箭头函数(()=>add())和直接传递函数引用add”间的差异引出的“箭头函数和普通函数的区别”以及“this指向”等问题

69 阅读2分钟

一、 箭头函数(()=>add())和直接传递函数引用

1.1 在多数情况下是等价的

  1. 在事件处理的上下文,通常是等价的。事件触发都会调用add函数(函数式)
<Button title="+" onPress={add} />
<Button title="+" onPress={()=> { add() }} />

1.2 在以下情况下有所不同

  1. 传递参数
    • 需要传递参数给事件处理函数,直接传递函数引用不在适用
    <Button title="+" onPress={()=> { add(1) }} />
    
  2. 类式组件中 普通函数 绑定上下文(显式绑定)
class MyComponent extends React.Component {
    // 普通函数
    constructor(props) {
        super(props)
        this.add = this.add.bind(this);
    }
    add(param){  // 普通函数的this指向是动态的,取决于函数的调用方
        console.log(this); // 指向 MyComponent 实例 
        console.log(param); // 输出传递的参数
    }
    //箭头函数
    //add = (1) => {
    //  console.log(this);  // 指向MyComponent实例,箭头函数的this指向是静态,在函数定义时指向上下文
    //}
    render() {
        return <Button title="+" onPress=(this.add(1))>
    }
}
  1. 性能考虑

    • 函数组件中,每次函数渲染都会重新创建箭头函数
    <Button title="+" onPress={() => { add() }} />
    
    • 直接函数引用不会每次渲染创建
    <Button title="+" onPress={add} />
    
    • 另一种方法是预先绑定参数的函数。这种方法可以避免在 render 方法中创建新的箭头函数,从而提高性能。
    import React, { Component } from 'react';
    import { Button, View } from 'react-native';
    
    class MyComponent extends Component {
      handleClick = (param) => {
        console.log(this); // 指向 MyComponent 实例
        console.log(param); // 输出传递的参数
      }
    
      createHandleClickWithParam = (param) => {
        return () => this.handleClick(param);
      }
    
      render() {
        return (
          <View>
            <Button title="Click me" onPress={this.createHandleClickWithParam('Hello')} />
          </View>
        );
      }
    }
    
    export default MyComponent;
    

在这个示例中,createHandleClickWithParam 方法返回一个箭头函数,该箭头函数调用 handleClick 并传递参数。这样可以避免在 render 方法中创建新的箭头函数。

二. 箭头函数和普通函数的区别

使用箭头函数

在类组件中使用箭头函数定义方法时,this 会指向类实例。

import React, { Component } from 'react';
import { Button, View } from 'react-native';

class MyComponent extends Component {
  handleClick = (param) => {
    console.log(this); // 指向 MyComponent 实例
    console.log(param); // 输出传递的参数
  }

  render() {
    return (
      <View>
        <Button title="Click me" onPress={() => this.handleClick('Hello')} />
      </View>
    );
  }
}

export default MyComponent;

在这个示例中,handleClick 是一个箭头函数,因此它的 this 会指向 MyComponent 实例。即使在 render 方法中使用箭头函数来调用 handleClickthis 仍然会正确绑定。

使用普通函数

如果你使用普通函数定义方法,你需要显式绑定 this,否则 this 的值可能会不正确。

import React, { Component } from 'react';
import { Button, View } from 'react-native';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(param) {
    console.log(this); // 指向 MyComponent 实例
    console.log(param); // 输出传递的参数
  }

  render() {
    return (
      <View>
        <Button title="Click me" onPress={() => this.handleClick('Hello')} />
      </View>
    );
  }
}

export default MyComponent;

在这个示例中,handleClick 是一个普通函数,因此我们需要在构造函数中使用 bind 方法显式绑定 this,确保 this 指向 MyComponent 实例。

总结

  • 箭头函数的 this:箭头函数不会创建自己的 this,而是捕获其定义时所在上下文的 this,在类组件中通常指向类实例。

  • 普通函数的 this:普通函数会根据调用方式动态绑定 this,需要显式绑定以确保 this 指向类实例。