面试题:在 React 中,super() 和 super(props) 有什么区别?

这是一道考察React类组件继承原理JavaScript的class继承机制的经典面试题。很多人知道要用super(props),但说不出具体原因。

下面从JavaScript原型链、React内部实现、以及实际影响三个层面来拆解。


一、核心结论

在React类组件中,super(props)是标准写法,super()在某些情况下也能工作,但会导致this.props在构造函数中为undefined

具体区别:

写法this.props在构造函数中的值是否推荐
super()undefined❌ 不推荐
super(props)传入的props对象✅ 标准写法

二、JavaScript层面的原因

1. super()的作用

在ES6的class继承中,super()调用父类的构造函数

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

class Child extends Parent {
  constructor(name, age) {
    super(name);  // 调用 Parent.constructor
    this.age = age;
  }
}

规则: 在子类构造函数中,this必须在使用前通过super()初始化。不调用super()会报错。

2. super(props) vs super() 的差异

关键在于:父类(React.Component)的构造函数对props做了什么?

简化版的React.Component实现:

class Component {
  constructor(props) {
    this.props = props;  // 将props挂载到实例上
    // ... 其他初始化
  }
}
  • super(props):将props传给父类构造函数 → 父类执行this.props = props → 子类实例上有了props
  • super():没有传props → 父类构造函数中this.props = undefined → 子类实例上this.propsundefined

三、React中的实际影响

场景1:在构造函数中访问this.props

class MyComponent extends React.Component {
  constructor(props) {
    super();  // ❌ 没有传props
    console.log(this.props); // undefined
  }

  render() {
    console.log(this.props); // ✅ 有值(React在渲染前会补上)
    return <div>{this.props.name}</div>;
  }
}

关键点:

  • 构造函数中的this.propsundefined
  • render方法中的this.props有值,因为React在调用render之前会重新设置this.props

场景2:在构造函数中使用this.props做初始化

class MyComponent extends React.Component {
  constructor(props) {
    super(props);  // ✅ 正确
    this.state = {
      count: this.props.initialCount  // 需要props
    };
  }
}

如果使用super()this.props.initialCount就是undefined,导致初始化错误。


四、为什么super()render中也能工作?

React内部在实例化组件后,会做额外的处理:

// React内部简化逻辑
const instance = new YourComponent(props);  // 此时实例的this.props可能不正确
instance.props = props;  // React会重新赋值一次
instance.state = ...;

所以即使构造函数中this.propsundefined,在调用render前React会把它纠正过来。

但这依赖React的内部实现,不是标准行为,不应该依赖。


五、为什么官方推荐super(props)

  1. 保证构造函数中能正确使用this.props
    如果需要在constructor中读取props做初始化,super()会出错。
  2. 符合ES6规范
    子类构造函数应该完整地传递参数给父类构造函数。
  3. 避免依赖React的“修复”行为
    React的未来版本可能改变内部实现,依赖这种修复行为不安全。
  4. 代码可读性和一致性
    显式传递props让意图更清晰。

六、类组件中的完整标准写法

class MyComponent extends React.Component {
  constructor(props) {
    super(props);  // ✅ 必须这样写
    // 现在可以安全地使用 this.props
    this.state = {
      value: this.props.initialValue || ''
    };
  }

  render() {
    // 这里访问 this.props 也没问题
    return <div>{this.props.value}</div>;
  }
}

七、面试中的常见追问

追问1:如果构造函数中不需要使用this.props,可以用super()吗?

答: 技术上可以,但不推荐。原因:

  • 如果将来有人在构造函数中添加对this.props的引用,代码会静默失败(得到undefined而不是报错)。
  • 不符合React官方规范(文档明确要求super(props))。
  • 是一种“坏味道”,表明对继承机制理解不清。

追问2:函数组件中没有这个问题?

答: 对。函数组件没有constructor,也没有继承React.Component,所以不存在super调用。这也是函数组件更简单的原因之一。

追问3:如果忘记写super()会怎样?

答:

constructor(props) {
  // 没有调用 super()
  this.state = {}; // ❌ ReferenceError: Must call super constructor
}

JavaScript会直接报错,因为子类构造函数中必须在使用this前调用super()


八、面试参考答案(精简版)

super(props)super()的区别在于:super(props)会将props传递给父类React.Component的构造函数,让父类把props挂载到this.props上。而super()不会传递props,导致在子类的constructorthis.propsundefined。虽然在render方法中React会重新给this.props赋值,但官方仍然强制要求使用super(props),以确保构造函数中也能正确访问props,同时符合ES6的继承规范。”

THE END
喜欢就支持一下吧
点赞10 分享