JavaScript 原型继承详解:从类模拟到多态实现

作者:拾光时间:2026-10-26 13:08:20浏览:263

本文深入解析 JavaScript 基于原型的面向对象编程机制。通过构造函数模拟类定义,详细演示了如何在构造函数内部及 prototype 对象上添加属性与方法。重点讲解了利用原型链实现类继承的具体步骤,包括子类对父类方法的继承与重写,从而实现多态效果,并探讨了实例级别动态添加属性的技巧。

JavaScript 原型继承概述

在之前的项目中曾使用 Ext4 构建 Web 桌面环境,这促使我对 JavaScript 进行了更深入的学习。此前对 JavaScript 的认知仅局限于 document.getElementById() 和 alert() 等基础 API,如今正逐步深入理解其核心机制。若文中存在疏漏,欢迎指正。


JavaScript 是一种基于对象的语言,传统意义上并不具备“类”的概念。因此,实现继承主要依赖 JavaScript 的原型机制(prototype)。注:原文此处有误,实际上也可通过 apply 和 call 方法实现继承效果,感谢 @记忆的森林 的提示。


由于 JavaScript 没有专门的类定义机制,我们可以通过函数嵌套来模拟类的行为。在 JavaScript 中,函数可以包含变量和其他函数。我们将变量视为类的属性,内部函数视为成员方法,而外层函数则被视为类本身。


模拟类的创建与属性方法定义

首先,我们定义一个“动物”类,实际上它是一个函数,可视为该类的构造函数。


代码如下:

 
function Animal(){
console.log('Call the constuctor.');
} 

接着,使用 new 关键字创建该类的实例。


var cat = new Animal();


至此,我们成功创建了一个实例。运行代码并通过调试工具查看,若看到 'Call the constructor' 的输出,即证明类创建成功。


接下来,我们可以为构造函数添加参数,例如:


代码如下:

 
function Animal(name){
this.name = name;
} 

这样即可创建实例并访问类的属性。


代码如下:

 
function myClass(name){
this.name = name;
} 
var cat = new myClass("Kate");
alert(cat.name);

通过上述方式,我们可以成功访问实例 cat 的 name 属性。


众所周知,动物具备跳跃和进食等行为。那么如何为类添加这些方法呢?参考以下两种方案。


方法一:直接在构造函数内部声明方法。


代码如下:

 
function Animal(name){
this.name = name; this.jump = function(){
alert (this.name + " is jumping...");
}; 
this.eat = function(){
alert (this.name + " is eatting...");
}; 
} 
var cat = new Animal("Kate");
alert(cat.name);
cat.jump();
cat.eat();

方法二:利用 prototype 属性为类添加方法。


代码如下:

 
function Animal(name){
this.name = name;
} 
Animal.prototype = {
type : 'cat',
jump : function(){
alert (this.name + " is jumping...");
}, 
eat : function(){
alert (this.name + " is eatting...");
} 
} 
var cat = new Animal("Kate");
alert(cat.name);
alert(cat.type);
cat.jump();
cat.eat();

同理,我们也可以使用相同的方法为类添加新属性,例如 type。


上文介绍了如何在 JavaScript 中创建类,以及为类添加属性和方法。接下来,我们将探讨如何实现类的继承。


基于原型链的类继承实现

要实现继承,我们可以利用 prototype 机制。首先声明一个 Dog 类(若不清楚请回顾上文),并让它继承 Animal 类。


代码如下:

 
function Dog(){};
Dog.prototype = new Animal("Henry");

随后,我们可以实例化一只新的狗 dog,并尝试调用其方法以验证是否成功。


代码如下:

 
function Dog(){};
Dog.prototype = new Animal("Henry");
var dog = new Dog();
dog.jump();
dog.eat();

如果代码无误,运行结果应显示提示 “Henry is jumping...” 和 “Henry is eatting...”。


多态与方法重写技巧

既然实现了类的继承,自然会联想到多态问题。


多态是指相同的操作或函数作用于多种类型的对象时,能获得不同的结果。不同对象收到同一消息可产生不同结果,这种现象称为多态。


通过继承,子类已继承父类的方法,但为了实现多态,必须对子类的方法进行重写。


为了更清晰地表达,我们再创建一个 Pig 类并继承 Animal 类。具体创建过程略去,创建后的代码如下所示。


代码如下:

 
function Dog(){};
Dog.prototype = new Animal("Henry");
function Pig(){};
Pig.prototype = new Animal("Coco");
var dog = new Dog();
dog.jump();
dog.eat();
var pig = new Pig();
pig.jump();
pig.eat();

运行后,由于继承了 Animal 类,结果仍会显示 “XX is jumping...” 和 “XX is eatting...”。为了实现多态,我们需要对方法进行重写,可采用以下方式。


代码如下:

 
function Dog(){};//创建dog子类
Dog.prototype = new Animal("Henry");
//重写dog的方法
Dog.prototype.jump = function(){
alert("Hi, this is " + this.name + ", I'm jumping...")
}; 
Dog.prototype.eat = function(){
alert("Henry is eatting a bone now.");
}; 
function Pig(){};//创建pig子类
Pig.prototype = new Animal("Coco");
//重写pig的方法
Pig.prototype.jump = function(){
alert("I'm sorry. " + this.name + " can not jump.");
}; 
Pig.prototype.eat = function(){
alert("Hi, I'm " + this.name + ", I'm eatting something delicious.");
} 
var dog = new Dog();
dog.jump();
dog.eat();
var pig = new Pig();
pig.jump();
pig.eat();

运行代码,是否成功实现了对方法的重写?


实例级别的动态属性与方法添加

此外,如果实例化一只 dog 后,想单独为该实例添加属性和方法,该如何操作?参考以下示例。


代码如下:

 
var dog = new Dog();
//添加属性和方法
dog.type = "Doberman Pinscher";
dog.shout = function(){
alert("I'm a " + this.type + ".");
} 
dog.jump();
dog.eat();
//调用新的方法
dog.shout();

至此,文章主要内容结束。希望初学者能通过本文对类的创建与继承有清晰的理解。如有问题,欢迎留言交流,感谢指教。


作者最新文章