javascript什么是原型链_它如何实现继承【教程】
技术百科
幻影之瞳
发布时间:2026-01-28
浏览: 次 原型链的本质是对象的__proto__指向其构造函数的prototype,通过[[Prototype]]内部属性实现属性查找委托,终点为null,Object.create()可手动构建,属性赋值不触发委托。
原型链的本质是对象的 __proto__ 指

prototype
JavaScript 中没有类继承,只有对象间委托——原型链就是这条委托链。每个对象都有一个内部属性 [[Prototype]](可通过 __proto__ 访问),它指向创建该对象的构造函数的 prototype 对象。当访问一个对象上不存在的属性时,JS 引擎会顺着 __proto__ 一层层向上查找,直到找到或抵达 null。
常见错误现象:
• 直接修改实例对象的 __proto__ 导致意外覆盖原型行为
• 误以为 Object.prototype.__proto__ === null 是特例,其实所有原型链终点都是 null
• 在 ES6 class 中误用 super() 前访问 this,本质是没理解 class 只是语法糖,底层仍依赖原型链初始化
用 Object.create() 手动构建原型链最直观
这是理解原型继承最干净的方式,绕过构造函数和 new 的干扰,直击委托关系。
-
Object.create(proto)创建一个新对象,其__proto__直接设为proto - 若想让子对象继承父对象的方法,就把父对象传给
Object.create() - 注意:
Object.create(null)创建的是“无原型”对象,查不到toString等内置方法
示例:
立即学习“Java免费学习笔记(深入)”;
const animal = { eats: true };
const cat = Object.create(animal);
cat.meows = true;
console.log(cat.eats); // true —— 从 animal 委托获得
构造函数 + prototype 是最常见的继承实现方式
虽然 ES6 后多用 class,但底层仍是这套机制。关键点在于:必须让子构造函数的 prototype 关联到父构造函数的实例(或至少是其原型),才能形成有效委托链。
- 错误写法:
Child.prototype = Parent.prototype—— 这会让子类直接污染父类原型 - 正确写法:
Child.prototype = Object.create(Parent.prototype),再补上constructor指回Child - 必须在重写
prototype后、添加实例方法前执行,否则新方法会丢失 - 调用父构造函数需显式用
Parent.call(this, ...),否则实例属性不会被初始化
ES6 class 和 extends 并未改变原型链逻辑
它只是把上述手动操作封装成更易读的语法,但运行时行为完全一致。编译后仍是设置 __proto__ 和 prototype 的关系。
-
class B extends A会自动设置B.__proto__ === A(静态继承)和B.prototype.__proto__ === A.prototype(实例继承) -
super()在子类构造器中必须调用,否则无法初始化this,本质是确保父构造函数被执行 - 箭头函数没有自己的
prototype,不能用作构造函数,也无法参与原型链继承
容易忽略的一点:原型链只对**属性读取**生效;属性赋值永远发生在当前对象自身,不会触发向上委托。这也是为什么 obj.prop = value 不会修改原型上的同名属性。
# js
# javascript
# java
# class
# 子类
# 构造函数
# 委托
# 为什么
# NULL
# 封装
# 继承
# Object
# 父类
# es6
相关栏目:
<?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订单日志怎么导出excel_php导出订单日
- c++如何实现一个高性能的环形队列(Ring Bu
- Windows7怎么找回经典开始菜单_Window
- 如何在Golang中解压文件_Golang com
- Mac的访达(Finder)怎么用_Mac文件管理
- 企业SEO优化选择网站建设模板的技巧
- Win11怎么设置快速访问_Windows11文件
- Windows10怎么备份注册表_Windows1
- Win11怎么设置屏保_Windows 11屏幕保
- Win11如何设置自动关机 Win11定时关机命令
- php8.4xdebug无法调试怎么办_php8.
- Python变量绑定机制_引用模型解析【教程】
- Python与GPU加速技术_CUDA与Numba
- VSC怎样在VSC中调试PHPAPI_接口调试技巧
- Win11怎么更改系统语言_Win11中文语言包下
- C#如何使用XPathNavigator高效查询X
- PythonFastAPI项目实战教程_API接口
- Win10怎么设置开机密码_Windows10账户
- c++的static关键字有什么用 静态变量和静态
- Windows电脑键盘突然失灵怎么办?(驱动与硬件
- Win11怎么设置任务栏对齐方式_Windows1
- Windows10系统怎么查看运行时间_Win10
- Python音视频处理高级项目教程_FFmpegP
- Windows家庭版如何开启组策略(gpedit.
- 使用类变量定义字符串常量时的类型安全最佳实践
- php本地部署支持nodejs吗_php与node
- windows 10应用商店区域怎么改_windo
- Win11如何关闭游戏模式 Win11禁用Xbox
- c++中如何进行二进制文件读写_c++ read与
- Win11任务栏怎么放到顶部_Win11修改任务栏
- Python并发安全问题_资源竞争说明【指导】
- Windows蓝屏错误0x00000018怎么处理
- 用Python构建微服务架构实践_FastAPI与
- Windows10如何删除Windows.old_
- 如何在 IIS 上为 ASP.NET 6 应用排除
- c# Task.Yield 的作用是什么 它和Ta
- 如何诊断并终止卡死的 multiprocessin
- 如何在 Go 开发中正确处理本地包导入与远程模块路
- Mac自带的词典App怎么用_Mac添加和使用多语
- 如何在Golang中实现并发消息队列消费者_Gol
- MAC如何设置网卡MAC地址克隆_MAC终端修改物
- Win10如何备份注册表_Win10注册表备份步骤
- Win11怎么设置默认终端应用_Windows11
- Win11怎么查看局域网电脑_Windows 11
- c# F# 的 MailboxProcessor
- 如何在Golang中处理云原生事件_使用Event
- Win11怎么关闭专注助手 Win11关闭免打扰模
- 如何使用Golang处理网络超时错误_Golang
- Windows资源管理器总是卡顿或重启怎么办?(修
- 如何在同包不同文件中正确引用 Go 结构体

QQ客服