详解JS面向对象编程:两种经典继承模式解析

作者:木棉

时间:2026-10-29

浏览:444

本文深入解析JavaScript基于原型的面向对象编程,重点介绍两种经典继承实现方式。第一种通过函数模拟类,利用prototype属性及uber机制实现方法调用;第二种采用拷贝继承,通过_this对象承载公有成员并传递至子类。文章结合具体代码示例,详细阐述变量可见性、构造函数修正及父类方法复写等核心细节,帮助开发者理解JS继承机制的本质。

文章目录

JavaScript面向对象基础与术语定义

由于JavaScript语言底层基于原型(prototype)机制,传统上并不存在“类”的概念(尽管ES6引入了class语法,此处暂不展开讨论),因此在JS中我们接触到的都是对象实例,这体现了“一切皆对象”的设计哲学。

鉴于“对象”一词在JS中含义较为宽泛,许多初学者容易混淆“类型对象”与“具体对象实例”的区别。为了便于理解,下文在术语使用上将借鉴Java等语言的分类方式,明确区分类型与实例。

基于函数模拟的继承模式

接下来介绍第一种实现方式。

类(函数模拟)


function Person(name,id){
 //实例变量可以被继承
 this.name = name;
 //私有变量无法被继承
 var id = id;
 //私有函数无法被继承
 function speak(){
  alert("person1");
 }
}
//静态变量,无法被继承
Person.age = 18;
//公有函数可以被继承
Person.prototype.say = function(){
 alert("person2");
}

实现继承,并调用父类方法。


function Person(name,id){
 //实例变量可以被继承
 this.name = name;
 //私有变量无法被继承
 var id = id;
 //私有函数无法被继承
 function speak(){
  alert("person1");
 }
}
//静态变量,无法被继承
Person.age = 18;
//公有静态成员可被继承
Person.prototype.sex = "男";
//公有静态函数可以被继承
Person.prototype.say = function(){
 alert("person2");
}
//创建子类
function Student(){
}
//继承person
Student.prototype = new Person("iwen",1);
//修改因继承导致的constructor变化
Student.prototype.constructor = Student;
var s = new Student();
alert(s.name);//iwen
alert(s instanceof Person);//true
s.say();//person2

实现继承,复写父类方法并模拟super()调用。


function Person(name,id){
 //实例变量可以被继承
 this.name = name;
 //私有变量无法被继承
 var id = id;
 //私有函数无法被继承
 function speak(){
  alert("person1");
 }
}
//静态变量,无法被继承
Person.age = 18;
//公有静态成员可被继承
Person.prototype.sex = "男";
//公有静态函数可以被继承
Person.prototype.say = function(){
 alert("person2");
}
//创建子类
function Student(){
}
//继承person
Student.prototype = new Person("iwen",1);
//修改因继承导致的constructor变化
Student.prototype.constructor = Student;
//保存父类的引用
var superPerson = Student.prototype.say;
//复写父类的方法
Student.prototype.say = function(){
 //调用父类的方法
 superPerson.call(this);
 alert("Student");
}
//创建实例测试
var s = new Student();
alert(s instanceof Person);//true
s.say();//person2 student

封装继承相关的辅助函数。


function extend(Child, Parent) {

    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
  }

其中,uber属性用于指向父对象的prototype属性(“uber”为德语,意为“向上”或“上一层”)。这相当于在子对象上建立了一条直接调用父对象方法的通道。该行代码主要用于保证继承结构的完备性,属于备用性质的设置。

基于拷贝与_this对象的继承模式

接下来介绍第二种实现方式。

这种方式相当于对象拷贝,通过定义一个_this对象来承载需要被继承的内容。通过传递这个_this对象,即可实现继承逻辑,相比前一种方式,其直观性更强,更易于理解。


//创建父类
function Person(name,id){
 //创建一个对象来承载父类所有公有东西
 //也就是说_this承载的对象才会被传递给子类
 var _this = {};
 _this.name = name;
 //这样的是不会传递下去的
 this.id = id;
 //承载方法
 _this.say = function(){
  alert("Person");
 }
 //返回_this对象
 return _this;
}
//子类
function Student(){
 //获取person的_this对象,从而模仿继承
 var _this = Person("iwne",1);
 //保存父类的_this引用
 var superPerson = _this.say;
 //复写父类的方法
 _this.say = function(){
  //执行父类的say
  superPerson.call(_this);
  alert("Student");
 }
 return _this;
}
var s = new Student();
s.say();

希望以上解析能对各位学习JavaScript程序设计有所帮助。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章