首页 > web前端 > js教程 > 正文

什么是原型链?原型继承的原理

煙雲
发布: 2025-08-24 12:03:01
原创
307人浏览过
原型链是JavaScript实现继承的核心机制,它通过对象的__proto__属性与构造函数的prototype属性链接,形成一条属性查找链。当访问对象属性时,若自身不存在,则沿原型链向上搜索,直至Object.prototype或null。prototype是函数独有的属性,指向实例的共享原型对象;__proto__是每个对象都有的内部属性,指向其构造函数的prototype。将方法定义在prototype上可实现内存共享,提升性能;通过Object.create()可构建继承关系,实现行为复用。原型链的动态性允许运行时修改共享方法,所有实例即时生效,但应避免修改内置对象原型以防冲突。理解原型链有助于写出高效、可维护的JavaScript代码。

什么是原型链?原型继承的原理

原型链是JavaScript中实现继承的核心机制,它允许对象从其他对象那里继承属性和方法。简单来说,当你尝试访问一个对象的某个属性或方法时,如果这个对象本身没有,JavaScript就会沿着一条由内部链接组成的“链条”向上查找,直到找到该属性或方法,或者查到链的尽头(通常是

null
登录后复制
)。这个查找的过程和链条本身,就是原型链。原型继承的原理,正是基于这种通过原型链进行属性查找和共享的机制。

JavaScript里,每个对象都有一个内部链接,指向另一个对象,这个被链接的对象就是它的“原型”(prototype)。当你在一个对象上访问一个属性时,如果它自身没有这个属性,JavaScript就会去它的原型上找。如果原型也没有,就继续找原型的原型,如此往复,直到找到

Object.prototype
登录后复制
(大多数对象的原型链最终都会指向这里),如果还没找到,那就返回
undefined
登录后复制
。这个查找路径,就是原型链在起作用。

举个例子,你创建一个构造函数,比如

function Person(name) { this.name = name; }
登录后复制
。然后你用
new Person('张三')
登录后复制
创建了一个实例
zhangsan
登录后复制
。这个
zhangsan
登录后复制
对象会有一个内部链接(也就是我们常说的
__proto__
登录后复制
),指向
Person.prototype
登录后复制
这个对象。如果你在
zhangsan
登录后复制
上调用一个方法,比如
zhangsan.sayHello()
登录后复制
,而
zhangsan
登录后复制
本身没有
sayHello
登录后复制
方法,JavaScript就会去
Person.prototype
登录后复制
上找。如果
Person.prototype
登录后复制
上有,那就用它。如果
Person.prototype
登录后复制
也没有,那它也会有自己的
__proto__
登录后复制
指向
Object.prototype
登录后复制
,查找就会继续下去。这种层层递进的关系,构建了原型链,也成就了JavaScript的继承。

__proto__
登录后复制
prototype
登录后复制
有什么区别

这是很多初学者都会犯迷糊的地方,也确实是理解原型链的关键所在。简单点说,

prototype
登录后复制
是一个函数才有的属性,它指向一个对象,这个对象就是未来通过该函数构造出来的所有实例的公共祖先。你可以把所有共享的方法和属性都放在这个
prototype
登录后复制
对象上。比如,
Person.prototype
登录后复制
就是所有
Person
登录后复制
实例的“共享仓库”。

__proto__
登录后复制
(注意,这是个非标准的属性,虽然现代浏览器都支持,但更推荐使用
Object.getPrototypeOf()
登录后复制
Object.setPrototypeOf()
登录后复制
)则是每个对象实例都有的属性,它指向创建这个实例的构造函数的
prototype
登录后复制
对象。所以,当你创建一个
zhangsan
登录后复制
对象,它的
zhangsan.__proto__
登录后复制
就指向
Person.prototype
登录后复制
。这就像是,
prototype
登录后复制
是图纸,而
__proto__
登录后复制
是根据图纸造出来的每件产品上,那个指向图纸的标记。一个在函数身上,一个在对象实例身上,作用完全不同,但又紧密相连,共同构成了原型链。

为什么说原型链是JavaScript实现继承的核心?

我觉得,把原型链看作JavaScript实现继承的核心,是因为它提供了一种非常灵活且高效的机制,与传统的基于类的继承模型截然不同。在JavaScript中,没有像Java或C++那样的“类”的概念(ES6的

class
登录后复制
语法也只是语法糖,底层依然是原型链)。所有的对象都是通过原型链相互关联,从而实现属性和方法的共享。

这种机制的妙处在于:

  1. 资源共享与节约内存: 想象一下,如果你有成千上万个
    Person
    登录后复制
    实例,每个实例都有一个
    sayHello
    登录后复制
    方法。如果这个方法直接定义在每个实例内部,那内存消耗会非常大。但如果把
    sayHello
    登录后复制
    定义在
    Person.prototype
    登录后复制
    上,所有实例都通过原型链共享同一个方法,大大节约了内存。这对于大规模应用来说,是实实在在的性能提升。
  2. 动态性: 原型链是动态的。你可以在运行时修改一个构造函数的
    prototype
    登录后复制
    对象,比如添加一个新的方法。那么,所有基于这个构造函数创建的实例(包括那些已经创建的),都会立即“继承”到这个新的方法。这种灵活性是类继承模型很难比拟的。
  3. 行为复用: 它让代码复用变得简单直接。你不需要复杂的类层次结构,只需要通过设置对象的原型,就能让它拥有另一个对象的行为。

所以,原型链不仅仅是一种技术实现,它更是JavaScript这门语言设计哲学的一部分,强调对象的关联而非僵硬的分类。

可图大模型
可图大模型

可图大模型(Kolors)是快手大模型团队自研打造的文生图AI大模型

可图大模型 32
查看详情 可图大模型

实际开发中,我们如何利用原型链进行优化?

在实际开发中,理解并恰当利用原型链,确实能帮助我们写出更高效、更易维护的代码。

一个最常见的优化点就是将方法定义在构造函数的

prototype
登录后复制
。而不是直接在构造函数内部用
this.method = function() {}
登录后复制
的方式定义。

// 不推荐:每次创建实例都会生成新的方法
function DogBad(name) {
    this.name = name;
    this.bark = function() {
        console.log(this.name + ' says woof!');
    };
}

// 推荐:方法定义在原型上,所有实例共享
function DogGood(name) {
    this.name = name;
}

DogGood.prototype.bark = function() {
    console.log(this.name + ' says woof!');
};

const dog1 = new DogGood('Buddy');
const dog2 = new DogGood('Lucy');
dog1.bark(); // Buddy says woof!
dog2.bark(); // Lucy says woof!
// console.log(dog1.bark === dog2.bark); // true,因为它们引用的是同一个函数
登录后复制

通过这种方式,

bark
登录后复制
方法只在内存中存在一份,所有
DogGood
登录后复制
的实例都通过原型链去访问它,大大减少了内存开销。

另外,在某些场景下,我们可以利用原型链实现简单的继承。比如:

function Animal(name) {
    this.name = name;
}
Animal.prototype.eat = function() {
    console.log(this.name + ' is eating.');
};

function Cat(name) {
    Animal.call(this, name); // 继承父类的属性
}

// 核心:设置Cat的原型链,使其指向Animal的实例
// 这样Cat的实例就能通过原型链访问到Animal.prototype上的方法
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat; // 修正constructor指向

Cat.prototype.meow = function() {
    console.log(this.name + ' says meow!');
};

const myCat = new Cat('Tom');
myCat.eat(); // Tom is eating. (继承自Animal.prototype)
myCat.meow(); // Tom says meow! (Cat自身的方法)
登录后复制

这里

Object.create(Animal.prototype)
登录后复制
是关键,它创建了一个新对象,并把这个新对象的
__proto__
登录后复制
指向了
Animal.prototype
登录后复制
。然后我们把
Cat.prototype
登录后复制
指向这个新对象,这样就建立起了
Cat
登录后复制
实例到
Animal.prototype
登录后复制
的原型链。修正
constructor
登录后复制
属性也很重要,否则所有
Cat
登录后复制
实例的
constructor
登录后复制
会指向
Animal
登录后复制

当然,也有一些需要谨慎对待的地方。比如,不推荐直接修改内置对象(如

Array.prototype
登录后复制
Object.prototype
登录后复制
)的原型
,除非你非常清楚自己在做什么。因为这可能会导致“污染”全局环境,与其他库或未来的JavaScript版本产生冲突,引发难以预料的bug。

总的来说,原型链是JavaScript的基石,理解它能让你更深入地掌握这门语言,写出更符合其设计哲学的代码,从而在性能和维护性上都有所提升。

以上就是什么是原型链?原型继承的原理的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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