返回首页

super() 和 super(props) 有什么区别?

问题解析(面试官考察点)

面试官通过此问题主要考察:

  • 对 ES6 类继承机制的理解
  • 对 React 类组件构造函数执行流程的掌握
  • 是否了解 this 的绑定时机
  • 对 React 内部实现的一定了解

核心概念(基础知识点)

ES6 中的 super

在 ES6 中,通过 extends 关键字实现类的继承,super 代表父类的构造函数:

class Sup {
  constructor(name) {
    this.name = name;
  }

  printName() {
    console.log(this.name);
  }
}

class Sub extends Sup {
  constructor(name, age) {
    super(name); // 调用父类构造函数
    this.age = age;
  }

  printAge() {
    console.log(this.age);
  }
}

let jack = new Sub("jack", 20);
jack.printName(); // 输出: jack
jack.printAge();  // 输出: 20

为什么必须使用 super()

子类没有自己的 this 对象,必须继承父类的 this 对象:

class Sub extends Sup {
  constructor(name, age) {
    // 错误:必须先调用 super 才能使用 this
    this.age = age; // ReferenceError: Must call super constructor
    super(name);
  }
}

详细解答(代码示例)

React 类组件中的 super()

class Button extends React.Component {
  constructor(props) {
    super(); // 没有传入 props
    console.log(props);      // {} - 参数可以访问
    console.log(this.props); // undefined - this.props 未定义
  }
}

React 类组件中的 super(props)

class Button extends React.Component {
  constructor(props) {
    super(props); // 传入了 props
    console.log(props);      // {} - 参数可以访问
    console.log(this.props); // {} - this.props 已定义
  }
}

没有 constructor 的情况

class HelloMessage extends React.Component {
  render() {
    // 没有 constructor,this.props 仍然可以访问
    return <div>nice to meet you! {this.props.name}</div>;
  }
}

推荐写法

class MyComponent extends React.Component {
  constructor(props) {
    super(props); // 推荐写法
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>Props: {this.props.title}</p>
        <p>State: {this.state.count}</p>
      </div>
    );
  }
}

深入理解(原理剖析)

React 内部如何处理 props

React 内部实现大致如下:

// React 内部伪代码
const instance = new YourComponent(props);
instance.props = props; // 在构造函数执行后才赋值

这意味着:

  • 如果不传递 propssuper()this.props 在构造函数执行期间是 undefined
  • React 会在构造函数执行完毕后给 this.props 赋值

执行时序分析

class Button extends React.Component {
  constructor(props) {
    // 1. super() 执行前:this 不存在
    super(props);
    // 2. super(props) 执行后:this 存在,this.props = props

    console.log(this.props); // 可以访问

    // 3. 构造函数执行完毕
    // 4. React 内部:instance.props = props(如果没有传 props)
  }
}

使用场景对比

场景 使用 super() 使用 super(props)
构造函数中访问 this.props undefined 可以访问
render 中访问 this.props 可以访问 可以访问
其他生命周期访问 this.props 可以访问 可以访问

为什么建议使用 super(props)

  1. 符合逻辑:确保 this.props 在构造函数执行完毕之前已被赋值
  2. 避免错误:如果在构造函数中需要使用 this.props,不会得到 undefined
  3. 代码一致性:统一写法,避免混淆

最佳实践

推荐写法

class MyComponent extends React.Component {
  constructor(props) {
    super(props); // 始终传递 props
    this.state = {
      // 初始状态
    };
  }
}

简化写法(不需要 constructor)

class MyComponent extends React.Component {
  state = {
    count: 0
  };

  render() {
    return <div>{this.props.title}</div>;
  }
}

箭头函数绑定(不需要 constructor)

class MyComponent extends React.Component {
  state = {
    count: 0
  };

  handleClick = () => {
    // 自动绑定 this
    console.log(this.props.title);
  };

  render() {
    return <button onClick={this.handleClick}>Click</button>;
  }
}

使用函数组件(推荐)

function MyComponent(props) {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{props.title}</p>
      <p>{count}</p>
    </div>
  );
}

面试要点

  1. 核心区别

    • super():父类构造函数执行后,this.propsundefined
    • super(props):父类构造函数执行后,this.props 已赋值
  2. ES6 类继承规则

    • 子类必须在 constructor 中先调用 super() 才能使用 this
    • super() 相当于调用父类的构造函数
  3. React 的特殊处理

    • 无论是否写 constructor,React 都会自动处理 props
    • render 和其他生命周期中,this.props 总是可以访问
  4. 常见误区

    • 不写 constructor 时,this.props 仍然可以访问(React 自动处理)
    • 写了 constructor 但不传 propssuper,构造函数中 this.propsundefined
  5. 现代 React 建议

    • 优先使用函数组件 + Hooks
    • 类组件中尽量省略 constructor,使用类属性语法
    • 如果必须写 constructor,始终使用 super(props)
  6. 相关面试题

    • 为什么类组件需要写 super?
    • super() 和 super(props) 的区别?
    • 不写 constructor 可以访问 this.props 吗?
    • 在 constructor 中调用 this.props 有什么风险?