原生 JavaScript 构造函数可用于模拟类组件雏形,constructor 负责初始化状态和 DOM 引用,render 方法负责渲染,需避免在 constructor 中调用 render、操作外部 DOM 或执行异步操作。

在现代 JavaScript(尤其是 ES6+)中,构造函数本身并不直接用于初始化组件,这是 React、Vue 等框架的抽象概念。原生 JavaScript 没有“组件”内置模型,但你可以用构造函数模拟可复用的、带状态和行为的 UI 单元——也就是“类组件”的雏形。关键在于:构造函数负责初始化实例属性(如数据、DOM 引用、事件绑定),而“渲染”需额外方法配合。
用 class 构造函数创建可复用的 UI 类
ES6 class 本质是构造函数语法糖。你可以定义一个类,其 constructor 初始化内部状态和基础 DOM 结构:
- 在
constructor中接收配置参数(如容器、初始数据) - 创建并缓存 DOM 元素(避免重复查询)
- 设置默认状态(
this.state = {...}) - 不在此处操作真实 DOM 渲染(留到单独的
render()方法)
示例:
class Counter {
constructor(container, initialState = 0) {
this.container = typeof container === 'string'
? document.querySelector(container)
: container;
this.state = { count: initialState };
this.$el = null; // 渲染后赋值
}
render() {
const html = `
<div class="counter">
<span>Count: ${this.state.count}</span>
<button onclick="this.parentElement.__handleClick()">+</button>
</div>
`;
this.container.innerHTML = html;
this.$el = this.container.firstElementChild;
// 绑定 this 到实例(注意:内联 onclick 需手动代理)
this.$el.__handleClick = () => this.increment();
}
increment() {
this.state.count++;
this.render(); // 简单重绘(实际项目建议 diff 或局部更新)
}
}
// 使用
const counter = new Counter('#app', 5);
counter.render();
构造函数里要避开的常见坑
- 不要在 constructor 中调用 render():此时 DOM 可能未就绪,且违反单一职责(构造只负责初始化)
-
避免直接操作外部 DOM 状态:比如修改全局样式或未受控的父容器内容,应通过明确接口(如
mount()/unmount())管理生命周期 -
异步初始化需另设方法:构造函数必须同步返回实例,API 请求、动态 import 等应放在
init()或async mount()中 -
事件监听器记得清理:若在 constructor 中绑定(如
window.addEventListener),需配套销毁逻辑,否则内存泄漏
和现代框架对比的关键差异
- React 的
constructor(props)主要用于初始化this.state和绑定方法,render是纯函数,不操作 DOM - Vue 2 的
data()函数替代了构造函数初始化状态,Vue 3 的setup()更彻底脱离 class 构造逻辑 - 原生构造函数没有虚拟 DOM、响应式系统或生命周期钩子(mounted、updated),这些都得自己实现
如果你在用 React/Vue/Angular,就别手写构造函数初始化组件——直接用框架约定的方式(如 React 的 useState + 函数组件,或 Vue 的 defineComponent)。只有在写轻量工具库、定制表单控件或教学演示时,才值得用构造函数封装一个“类组件”原型。
立即学习“Java免费学习笔记(深入)”;


















