javascript中的类与继承是如何实现的【教程】
技术百科
幻影之瞳
发布时间:2026-01-27
浏览: 次 JavaScript的类是基于原型的语法糖,class声明本质是函数加prototype操作,实例属性须在constructor中用this显式初始化,继承必须正确调用super()以维护原型链。
JavaScript 的类和继承不是传统面向对象语言那种“编译时确定的类型系统”,而是基于原型(prototype)的语法糖——class 关键字本身不创建新机制,只是让原型链操作更可读、更结构化。
class 声明本质是函数 + prototype 操作
class 声明会被 JavaScript 引擎转为一个具有 constructor 属性的函数,并自动设置其 prototype。你不能在 class 内部用 = 直接给实例赋值成员变量(像 Python 那样),所有实例属性必须在 constructor 中通过 this.xxx = 显式初始化。
-
class Person {}等价于function Person() {},且Person.prototype自动存在 - 类方法(如
sayHello())被添加到Person.prototype上,不是每个实例都拷贝一份 - 类中不允许写
var name = 'xxx'这样的语句;静态属性需用Person.version = 1或static version = 1(ES2025+)
extends 和 super 的调用顺序很关键
子类构造函数中,必须在访问 this 前调用 super()——否则会抛出 ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor。这是因为子类实例的内部槽([[Prototype]])依赖 super() 来正确链接到父类原型。
-
super()必须出现在constructor第一行(或至少在任何this访问之前) -
super.xxx可用于访问父类原型上的方法,但不能在super()调用前使用 - 如果子类没写
constructor,引擎会自动注入constructor(...args) { super(...args); }
继承链断裂常见于手动改写 prototype
直接赋值 Child.prototype = Parent.prototype 或 Child.prototype = new Parent() 是危险操

constructor 指针和 __proto__ 链。
- 正确做法始终是用
extends,它底层调用Object.setPrototypeOf(Child.prototype, Parent.prototype) - 若必须手写继承(如兼容老环境),应使用
Object.create(Parent.prototype)并重设constructor -
instanceof判断依赖原型链,手动改错prototype会导致new Child() instanceof Parent === false
真正容易被忽略的是:类字段声明(name = 'x')属于 ES2025 提案,Babel 默认不编译它为可兼容代码;而 static 字段、私有字段(#age)的运行时行为与普通属性完全不同——它们不走 prototype,也不参与 for...in 遍历。别假设“写了 class 就等于 Java 那套”。
# 的是
# 也不
# 能在
# 写了
# 出现在
# python
# 但不
# 会让
# 你不
# 对象
# javascript
# java
# class
# 指针
# 子类
# 构造函数
# access
# Static
# function
# var
# this
# 成员变量
# 继承
# Object
# 遍历
# for
# 父类
# 面向对象
# constructor
# prototype
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 获取 PHP 文件最后修改时间的正确方法
- Go 中 defer 语句在 goroutine
- Win11怎样安装剪映专业版_Win11安装剪映教
- 如何在Golang中实现基础配置管理功能_Gola
- Windows10如何更改系统字体大小_Win10
- Win11怎么开启自动HDR画质_Windows1
- Win11怎么清理C盘虚拟内存_Win11清理虚拟
- 如何在Golang中验证模块完整性_Golangg
- Go 中 := 短变量声明的类型推导机制详解
- c++怎么处理多线程死锁_c++ lock_gua
- php在Linux怎么部署_LNMP环境搭建PHP
- PythonGIL机制理解_多线程限制解析【教程】
- Windows10蓝屏代码DPC_WATCHDOG
- Mac怎么进行语音输入_Mac听写功能设置与使用【
- Win11任务栏怎么放到顶部_Win11修改任务栏
- Win11怎么设置任务栏大小_Windows11注
- Win11怎么检查TPM2.0模块_Windows
- Windows系统被恶意软件破坏后的恢复策略_错误
- Windows10系统怎么查看显卡型号_Win10
- 如何在Golang中实现并发消息队列消费者_Gol
- Windows10电脑怎么设置文件权限_Win10
- Win11截图快捷键是什么_Win11自带截图工具
- Win11怎么清理C盘系统日志_Win11清理系统
- Linux怎么实现内网穿透_Linux安装Frp客
- MAC怎么用连续互通相机里的“桌上视角”_MAC在
- 如何使用Golang写入二进制文件_Golang
- Win11怎么关闭触摸键盘图标_Windows11
- Win11键盘快捷键大全_Windows 11常用
- Win11怎么设置快速访问_Windows11文件
- Windows执行文件被SmartScreen拦截
- PythonPandas数据分析教程_数据清洗与处
- 如何在Golang中实现CI/CD流水线自动化测试
- Linux怎么设置磁盘配额_Linux系统Quot
- Win11怎么制作U盘启动盘_Win11原版系统安
- Python异步网络编程_aiohttp说明【指导
- php485读数据时阻塞怎么办_php485非阻塞
- c++如何连接Redis c++ hiredis库
- Python生成器表达式内存优化_惰性计算说明【指
- Go语言中slice追加操作的底层共享机制解析
- Win11时间格式怎么改成12小时制 Win11时
- C#怎么使用委托和事件 C# delegate与e
- 如何使用Golang模拟请求超时_Golang c
- LINUX如何删除用户和用户组_Linux use
- C#如何在一个XML文件中查找并替换文本内容
- php中$this和::能混用吗_对象与静态作用域
- Linux如何申请SSL免费证书_Linux下Ce
- 如何使用Golang benchmark测量函数延
- MAC怎么在照片中添加水印_MAC自带编辑工具文字
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Win11应用商店下载慢怎么办 Win11更改DN

QQ客服