JavaScript 面向对象编程:深入理解继承机制

作者:函数茶馆

时间:2026-10-29

浏览:639

本文深入解析 JavaScript 中的继承概念,通过人类、中国人及美国人的示例,演示如何模拟面向对象继承。文章对比了仅继承原型行为与从父类实例复制属性的两种实现方式,详细讲解了 Extend 函数的编写、typeof 运算符在属性检测中的应用,以及多重继承的实现方法,旨在帮助开发者理解 OOP 核心思想并优化代码结构。

文章目录

JavaScript 继承概念引入

大家好,本节课程将在前文封装的基础上继续深入,重点讲解面向对象编程(OOP)中的核心概念——继承。我们将首先明确继承的定义及其在实际开发中的应用场景。

所谓继承,是指后代对象延续祖先对象的属性与行为特征。尽管存在差异,但后代仍归属于同一类别。接下来,我们将通过具体案例来深入理解这一概念。

JavaScript 继承概念引入

以现实世界为例,中国人和美国人都继承自“人类”这一祖先类别,因此他们拥有共同的属性与行为,同时也具备各自的特点。后续我们将探讨多态性。通过上述示例可知,个体间大同小异。结合下面的代码示例,我们可以发现,利用代码模拟继承机制,能够以极简的代码实现复杂的功能,达到事半功倍的效果。

原型链继承的初步实现


//遗传继承函数
function Extend(Children,Parent){
  //这里仅仅只是继承的原型链接定义的行为
  for(var p in Parent.prototype){
    Children[p] = Parent.prototype[p];
  }
}
//人类祖先
function Human(){
  this.weight = "50kg";
  this.height = "180cm";
  this.hair = "棕色";
}
//吃饭
Human.prototype.Eat = function(){
  console.log("吃饭");
}
//说话
Human.prototype.Say = function(){
  console.log("大家好我是地球人");
}
//行走
Human.prototype.Walk = function(){
  console.log("我是人类,天生就可以两条腿直立行走");
}
//繁衍
Human.prototype.Multiply = function(){
  console.log("跟老婆一起做羞羞的事,就是为了人类的繁荣");
}

//中国人
function Chinese(){
  //调用继承函数
  Extend(this,Human);
}
//美国人
function American(){
  //调用继承函数
  Extend(this,Human);
}

按照上述逻辑编写代码,即可在高级语言中模拟继承关系。接下来,我们将验证运行结果是否存在问题。

JavaScript 继承概念引入

运行后发现,虽然这种写法实现了基于原型链接的继承,并大幅减少了代码量——在定义 Chinese 和 American 函数时仅编写了少量代码便继承了父类行为,且实例也能调用父类方法——但这并非完整的继承实现。因为在访问 hair 属性时并未生效。因此,我们需要对代码进行修正,以实现完全继承。

基于实例属性的完整继承


//遗传继承函数
function Extend(Children,Parent){
  //现在我们是从父类实例来继承,所以属性和方法都会被继承的
  for(var p in Parent){
    if(typeof Children[p] == "undefined"){
      Children[p] = Parent[p];
    }
  }
}
//人类祖先
function Human(){
  this.weight = "50kg";
  this.height = "180cm";
  this.hair = "棕色";
}
//吃饭
Human.prototype.Eat = function(){
  console.log("吃饭");
}
//说话
Human.prototype.Say = function(){
  console.log("大家好我是地球人");
}
//行走
Human.prototype.Walk = function(){
  console.log("我是人类,天生就可以两条腿直立行走");
}
//繁衍
Human.prototype.Multiply = function(){
  console.log("跟老婆一起做羞羞的事,就是为了人类的繁荣");
}
//中国人
function Chinese(){
  //调用继承函数
  Extend(this,new Human());
}
//美国人
function American(){
  //调用继承函数
  Extend(this,new Human());
}

现在,让我们观察修正后的运行效果是否符合预期。

JavaScript 继承概念引入

通过上述代码可以看出,当前的继承函数实际上是从 Human 类的具体实例中复制了属性及行为。这使我们更贴近地模拟了类的完整继承过程。在此,需要补充解释一个关键点。


if(typeof Children[p] == "undefined"){
 ...... 
}

代码中出现的 typeof 关键字是一个运算符,用于判断变量的类型。若变量未定义,其运算结果为字符串 "undefined"。因此,我们通过比较判断:如果子类未定义特定属性或行为函数,则从父类继承(此解释旨在为后续的多态性讲解做铺垫)。

接下来,我们探讨是否支持多重继承。前文已提及 Chinese 和 American 类均继承自 Human 类。现在,我们编写一个新类来继承自 Chinese 类。

多重继承的实现与应用


//四川人
function SiChuanMan(){
  Extend(this,new Chinese());
}

JavaScript 继承概念引入

目前,我们已经编写出健壮且易于理解的继承代码。只需在声明新类时,在构造函数内调用继承函数,即可实现属性及行为函数的完全继承。这极大地节省了代码量,再次体现了 OOP 思想的优势。若要模拟中国各省份的人群,若每个省份都参照 Human 类的方式从头编写,工作量将极其巨大。继承的写法多种多样,个人风格各异。此处仅展示最简单的一种讲解方式,待大家熟练后,可采用自己喜欢的方式编写。JavaScript 本身即是一门极具灵活性的语言。

总结而言,我们在封装的基础上进行了升级,实现了对象的继承。代码量的进一步压缩不仅提升了工作效率,也增强了代码的优雅度。这是否让你感到些许兴奋?只要跟随教程步骤,我们就能用最简单的方式理解最复杂的概念。程序本身并不复杂,复杂的原因往往在于缺乏正确的引导、不同的理解与解释,以及缺乏连续且循序渐进的教程。因此,许多人在很长一段时间内难以获得提升。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章