0

0

js如何手动实现原型继承

星降

星降

发布时间:2025-08-18 12:29:01

|

1037人浏览过

|

来源于php中文网

原创

javascript中手动实现原型继承的核心是操作对象的[[prototype]]链,主要有两种方式:1. 使用object.create(),可直接创建以指定对象为原型的新对象,适合对象间直接继承;2. 通过构造函数结合prototype属性,将子类原型指向父类原型(child.prototype = object.create(parent.prototype)),并修正constructor指向,适用于模拟类式继承。理解手动继承有助于掌握js原型本质,避免this指向错误、constructor丢失、引用属性共享、for...in遍历原型属性及属性遮蔽等问题。

js如何手动实现原型继承

JavaScript中手动实现原型继承,核心就是通过操作对象的

[[Prototype]]
内部属性(通常通过
Object.create()
或直接修改构造函数的
prototype
属性)来建立一个原型链,让一个对象能够访问另一个对象的属性和方法。这并非什么黑魔法,更多的是理解JS对象之间联系的本质。

js如何手动实现原型继承

解决方案

说白了,手动实现原型继承,无非就是两种常见思路:

1. 使用
Object.create()

这是我个人觉得最直接、最优雅的方式之一,尤其当你只想让一个对象继承另一个对象,而不需要通过构造函数来实例化时。它允许你创建一个新对象,并指定它的原型。

js如何手动实现原型继承
// 父对象(或者说,你想继承的那个原型对象)
const parent = {
    value: 10,
    getValue() {
        return this.value;
    }
};

// 子对象,以 parent 为原型创建
const child = Object.create(parent);
child.value = 20; // 覆盖父对象的 value

console.log(child.getValue()); // 输出 20
console.log(Object.getPrototypeOf(child) === parent); // true
// 内部的 [[Prototype]] 链接被正确设置了

这里

child
对象并没有
getValue
方法,但它可以通过原型链找到
parent
上的
getValue
。这就像你家里的某个电器坏了,你不需要自己修,而是去找你爸妈(原型)帮忙一样。

2. 结合构造函数和
prototype
属性

这是ES6

class
语法糖背后,更“传统”的继承方式。本质上,是让一个构造函数的
prototype
对象指向另一个构造函数的实例,或者直接指向另一个原型对象。

js如何手动实现原型继承
// 父类构造函数
function Parent(name) {
    this.name = name;
}

Parent.prototype.sayHello = function() {
    console.log(`Hello, my name is ${this.name}.`);
};

// 子类构造函数
function Child(name, age) {
    Parent.call(this, name); // 继承父类的属性
    this.age = age;
}

// 核心:让 Child 的原型链指向 Parent 的原型对象
// 这样 Child 的实例就能访问 Parent.prototype 上的方法
Child.prototype = Object.create(Parent.prototype);
// 修正 constructor 指向,这步很重要,不然 constructor 会指向 Parent
Child.prototype.constructor = Child;

Child.prototype.sayAge = function() {
    console.log(`I am ${this.age} years old.`);
};

const childInstance = new Child('Alice', 5);
childInstance.sayHello(); // Hello, my name is Alice.
childInstance.sayAge();   // I am 5 years old.

console.log(childInstance instanceof Child); // true
console.log(childInstance instanceof Parent); // true

这种方式稍微复杂一点,但它模拟了经典的类继承模式。

Object.create(Parent.prototype)
这一步是关键,它创建了一个新对象,这个新对象的原型是
Parent.prototype
,然后我们把
Child.prototype
指向了这个新对象。这样,
child
的实例就能沿着原型链找到
parent
的方法。

为什么在ES6有了
class
之后,我们还需要理解手动原型继承?

说实话,这个问题我被问过好几次,每次我的答案都差不多:理解手动原型继承,不仅仅是为了应对老旧代码,更重要的是为了真正理解JavaScript这门语言的“骨架”。ES6的

class
语法确实让JS的面向对象编程看起来更像传统面向对象语言,写起来也更直观,但它本质上仍然是基于原型的。

在我看来,理解这些底层机制,就像你学开车,不能只知道踩油门刹车,还得懂点发动机原理。当你遇到一些奇奇怪怪的bug,或者需要做一些性能优化时,对原型链的深刻理解能帮你快速定位问题。比如,你可能会发现某个方法调用不对劲,一查才发现原型链上挂错了东西,或者

this
指向出了问题。这种知识储备,能让你在面对复杂系统时,有更清晰的“心智模型”。而且,很多库和框架,尤其是那些历史悠久的,内部可能就用了这些手动继承的模式,你不懂,就很难深入理解它们的设计哲学。

Object.create()
和直接修改
prototype
属性,它们在使用上有什么本质区别和适用场景?

这两种方式,虽然都能实现原型继承,但它们的侧重点和适用场景还是有挺大区别的。

原生js实现喜庆背景带炫酷雪花飘落动画特效代码
原生js实现喜庆背景带炫酷雪花飘落动画特效代码

原生js实现新年倒计时喜庆背景带炫酷雪花飘落动画特效代码下载。基于原生JavaScript+CSS实现,不依靠任何第三方jQuery库,兼容手机移动端,新年倒计时自动获取,可循环使用,非常简单实用的一款新年倒计时js特效代码。

下载

Object.create()
更像是一种“对象到对象”的继承。它直接创建一个新对象,并把指定对象设为它的原型。这个过程不涉及构造函数,也不需要通过
new
关键字。它的好处是简洁、直接,当你有一个现成的对象,想在此基础上扩展,或者实现一些类似“原型式继承”的模式时,
Object.create()
就显得特别顺手。比如,你想创建一个配置对象,它继承自一个默认配置,然后只覆盖其中几个属性,用
Object.create()
就很合适。

而通过修改构造函数的

prototype
属性,则是更“类式”的继承方式。它的核心思想是:所有由某个构造函数创建的实例,都应该共享同一个原型对象上的方法和属性。这种方式通常伴随着
new
关键字的使用,以及
Parent.call(this, ...)
来继承父类的实例属性。当你需要定义一个“类”的结构,并且希望通过这个“类”来创建大量具有相同行为的实例时,这种模式就非常适用。ES6的
class
语法就是这种模式的语法糖。

简单来说,

Object.create()
更灵活,适合一次性的对象继承或实现特定模式;而修改
prototype
则更偏向于构建可复用的“类”结构。

手动实现原型继承时,有哪些常见的“陷阱”和需要注意的细节?

说实话,手动实现原型继承,确实有几个地方是新手容易踩坑的。

一个很经典的“坑”就是

this
的指向问题。在原型链上的方法被调用时,
this
始终指向调用该方法的那个对象,而不是定义该方法的原型对象。这有时候会让人很困惑,特别是当方法内部需要访问实例特有的属性时。理解这一点,对于编写正确的原型方法至关重要。

接着,就是

constructor
属性的丢失。当你通过
Child.prototype = Object.create(Parent.prototype)
来设置原型时,
Child.prototype
会被一个全新的对象覆盖掉。这个新对象的
constructor
属性会指向
parent
,而不是
child
。这会导致
instanceof
操作符可能出现误判,或者当你需要通过
instance.constructor
来获取构造函数时,得到的结果不是你期望的。所以,我们通常需要手动加上一句
Child.prototype.constructor = Child;
来修正它。

再一个,是关于引用类型属性的共享问题。如果你的原型对象上有一个引用类型的属性(比如一个数组或对象),那么所有继承自这个原型的实例,都会共享这个引用。这意味着,如果你在一个实例上修改了这个引用类型的属性,所有其他实例上的这个属性也会跟着改变。这通常不是你想要的结果。解决办法通常是在构造函数内部创建实例独有的引用类型属性,而不是放在原型上。

还有一个小点,就是

for...in
循环。它会遍历对象自身以及原型链上所有可枚举的属性。如果你不加区分地使用它,可能会遍历到一些你不想要的、来自原型链的属性。通常我们会配合
hasOwnProperty()
方法来判断属性是否是对象自身的,以避免这种情况。

最后,就是属性的“遮蔽”(shadowing)。当一个实例拥有与原型链上同名的属性时,实例自身的属性会“遮蔽”原型上的属性。这意味着,当你访问这个属性时,会优先访问到实例自身的属性。这通常是预期的行为,但如果不理解,有时也会导致一些困惑。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

103

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

195

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

221

2025.12.24

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

52

2025.11.27

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

52

2025.11.27

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

光速学会docker容器
光速学会docker容器

共33课时 | 1.9万人学习

时间管理,自律给我自由
时间管理,自律给我自由

共5课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号