JavaScript面向对象三大特性详解:封装、继承与多态

作者:函数茶馆时间:2026-10-29 19:55:57浏览:587

本文详细解析JavaScript面向对象的三大核心特性:封装、继承与多态。通过构造函数、原型链、对象冒充及call/apply等方法,深入讲解如何实现数据隐藏、代码复用及多态行为,并结合具体代码案例说明各特性的应用场景与注意事项。

JavaScript面向对象特性概述

JavaScript中基于对象的三大特征与C++、Java等面向对象语言一致,均包含封装(encapsulation)、继承(inheritance)和多态(polymorphism)。尽管具体实现机制存在差异,但其核心概念基本相同。此外,部分资料中提及的“抽象(abstract)”通常也被视为面向对象的重要特征之一,因此有时可见“四大特征”的说法。

封装性的实现与注意事项

一、封装性 封装旨在将抽象出的数据及其操作绑定在一起,使数据受到保护并隐藏于内部。外部程序仅能通过被授权的成员方法对数据进行访问和操作。 案例:


<html> 
 <head> 
 <script type="text/javascript"> 
  function Person(name, agei, sal){ 
  // 公开 
  this.name = name; 
  // 私有 
  var age = agei; 
  var salary = sal; 
  } 
  var p1 = new Person('zs', 20, 10000); 
  window.alert(p1.name + p1.age); 
 </script> 
 </head> 
 <body> 
 </body> 
</html> 

注:在JavaScript中,封装主要体现为公开与私有两种状态。

通过构造函数与原型法添加成员方法的区别 1. 通过原型法分配的函数由所有对象共享。 2. 通过原型法分配的属性相互独立(若未修改属性,则表现为共享)。 3. 建议:若希望所有对象共用同一函数,推荐使用原型法添加函数,以节省内存空间。

案例:


function Person(){
 this.name="zs";
 var age=20;
 this.abc=function(){
 window.alert("abc");
 }
 function abc2(){
 window.alert("abc");
 }
}
Person.prototype.fun1=function(){
 window.alert(this.name);//ok
 //window.alert(age);//no ok
 //abc2();//no ok
 this.abc();//ok
}
var p1=new Person();
p1.fun1();

特别强调:前述通过prototype为所有对象添加方法的方式,无法访问类的私有变量和方法。

继承性的多种实现方式

二、继承性 继承旨在实现代码复用,使编程更贴近人类思维。当多个类拥有相同的属性(变量)和方法时,可从中抽象出父类,在父类中统一定义这些相同的属性和方法。所有子类无需重新定义,只需通过继承获取父类的属性和方法即可。 JS中实现继承的方式 1. 对象冒充 案例:


<html> 
 <head> 
 <script type="text/javascript"> 
  function Stu(name, age){ 
  this.name = name; 
  this.age = age; 
  this.show = function(){ 
   window.alert(this.name + " " + this.age); 
  } 
  } 
  function MidStu(name, age) { 
  this.stu = Stu; 
  // 通过对象冒充来实现继承的 
  // 对象冒充的意思就是获取那个类的所有成员,因为js是谁调用那个成员就是谁的,这样MidStu就有了Stu的成员了 
  this.stu(name, age); 
  this.payFee = function(){ 
   window.alert("缴费" + money * 0.8); 
  } 
  } 
  function Pupil(name, age) { 
  this.stu = Stu; 
  // 通过对象冒充来实现继承的 
  this.stu(name, age); 
  this.payFee = function(){ 
   window.alert("缴费" + money * 0.5); 
  } 
  } 
 
  var midStu = new MidStu("zs", 13); 
  midStu.show(); 
  var pupil = new Pupil("ls", 10); 
  pupil.show(); 
 </script> 
 </head> 
 <body> 
 </body> 
</html> 

2. 通过call或者apply实现 案例:


<html> 
<head> 
<script type="text/javascript"> 
 //1. 把子类中共有的属性和方法抽取出,定义一个父类Stu 
 function Stu(name,age){ 
 // window.alert("确实被调用."); 
 this.name=name; 
 this.age=age; 
 this.show=function(){ 
  window.alert(this.name+"年龄是="+this.age); 
 } 
 } 
 //2.通过对象冒充来继承父类的属性的方法 
 function MidStu(name,age){ 
 //这里这样理解: 通过call修改了Stu构造函数的this指向, 
 //让它指向了调用者本身. 
 Stu.call(this,name,age); 
 //如果用apply实现,则可以 
 //Stu.apply(this,[name,age]); //说明传入的参数是 数组方式 
 //可以写MidStu自己的方法. 
 this.pay=function(fee){ 
  window.alert("你的学费是"+fee*0.8); 
 } 
 } 
 function Pupil(name,age){ 
 Stu.call(this,name,age);//当我们创建Pupil对象实例,Stu的构造函数会被执行,当执行后,我们Pupil对象就获取从 Stu封装的属性和方法 
 //可以写Pupil自己的方法. 
 this.pay=function(fee){ 
  window.alert("你的学费是"+fee*0.5); 
 } 
 } 
 //测试 
 var midstu=new MidStu("zs",15); 
 var pupil=new Pupil("ls",12); 
 midstu.show(); 
 midstu.pay(100); 
 pupil.show(); 
 pupil.pay(100); 
</script> 
</html> 

小结: 1. JS对象可通过对象冒充实现多重继承。 2. Object类是所有JS类的基类。

多态性与函数重载机制

三、多态性 JS的函数重载 这是多态的基础。在之前的JavaScript入门知识中已提及,JS函数本身不支持传统意义上的多态,但事实上JS函数是无态的,支持任意长度和类型的参数列表。若同时定义多个同名函数,则以最后一个定义的函数为准。 案例:


<html> 
<head> 
<script type="text/javascript"> 
 //*****************说明js不支持重载***** 
 /*function Person(){ 
 this.test1=function (a,b){ 
  window.alert('function (a,b)'); 
 } 
 this.test1=function (a){ 
  window.alert('function (a)'); 
 } 
 } 
 var p1=new Person(); 
 //js中不支持重载. 
 //但是这不会报错,js会默认是最后同名一个函数,可以看做是后面的把前面的覆盖了。 
 p1.test1("a","b"); 
 p1.test1("a");*/ 
 
 //js怎么实现重载.通过判断参数的个数来实现重载 
 function Person(){ 
 this.test1=function (){ 
  if(arguments.length==1){ 
  this.show1(arguments[0]); 
  }else if(arguments.length==2){ 
  this.show2(arguments[0],arguments[1]); 
  }else if(arguments.length==3){ 
  this.show3(arguments[0],arguments[1],arguments[2]); 
  } 
 } 
 this.show1=function(a){ 
  window.alert("show1()被调用"+a); 
 } 
 this.show2=function(a,b){ 
  window.alert("show2()被调用"+"--"+a+"--"+b); 
 } 
 function show3(a,b,c){ 
  window.alert("show3()被调用"); 
 } 
 } 
 var p1=new Person(); 
 //js中不支持重载. 
 p1.test1("a","b"); 
 p1.test1("a"); 
</script> 
</html> 

1. 多态基本概念 多态指一个引用(类型)在不同情况下呈现多种状态。也可理解为:通过指向父类的引用,调用在不同子类中实现的方法。 案例:


<script type="text/javascript"> 
 // Master类 
 function Master(name){ 
 this.nam=name; 
 //方法[给动物喂食物] 
 } 
 //原型法添加成员函数 
 Master.prototype.feed=function (animal,food){ 
 window.alert("给"+animal.name+" 喂"+ food.name); 
 } 
 function Food(name){ 
 this.name=name; 
 } 
 //鱼类 
 function Fish(name){ 
 this.food=Food; 
 this.food(name); 
 } 
 //骨头 
 function Bone(name){ 
 this.food=Food; 
 this.food(name); 
 } 
 function Peach(name){ 
 this.food=Food; 
 this.food(name); 
 } 
 //动物类 
 function Animal(name){ 
 this.name=name; 
 } 
 //猫猫 
 function Cat(name){ 
 this.animal=Animal; 
 this.animal(name); 
 } 
 //狗狗 
 function Dog(name){ 
 this.animal=Animal; 
 this.animal(name); 
 } 
 //猴子 
 function Monkey(name){ 
 this.animal=Animal; 
 this.animal(name); 
 } 
 var cat=new Cat("猫"); 
 var fish=new Fish("鱼"); 
 
 var dog=new Dog("狗"); 
 var bone=new Bone("骨头"); 
 
 var monkey=new Monkey("猴"); 
 var peach=new Peach("桃"); 
 
 //创建一个主人 
 var master=new Master("zs"); 
 master.feed(dog,bone); 
 master.feed(cat,fish); 
 master.feed(monkey,peach); 
</script> 

多态有助于代码的维护和扩展。当需要使用同一类树上的对象时,只需传入不同的参数即可,无需再次new一个对象。

下面是其他网友的补充

其他网友补充与实战经验

分享Js一些基础理论知识,虽然在项目中十分实用。回想之前一次令人心碎的面试,等了将近50分钟,可是面试却不到10分钟,我的心里受到成吨的打击与伤害,以前一直不注重扎实基础,当面试官坐下的那一刻我就感到气氛不对,首先介绍自己软件工程毕业…….然后面试官说介绍一下软件的几大特性……..我…..我说不出话,然后跳过,让我介绍一下闭包、原型、js三大特性,以及在项目中的运用……我的天……当时脑海里浮现的全是我在哪….我是谁…..我在干嘛…..我还要继续坐在这里吗……可能现在说起来比较让人想笑,可是当时的心情确实是很难受的,所以,从那以后,开始注重自己的基础理论知识,好吧,让我们回到正题,let's go!

封装 首先,我们先了解一下什么是Js封装,就是当你需要隐藏一些属性和方法是,就可以将这些属性和方法封装起来,然后通过一个外部可以调用的特定接口(也可以说是一个公共的方法)进行调用。例如:


function Person(name , age , sex){
 this.name = name ; //共有变量 
 var age = age ; //私有变量
 var sex = sex ; //私有变量
 this.show = function (){
  console.log(age+"===="+sex);
 }
}
var person = new Person('Sunshine',18,'女');
console.log(person.age); // undefined
console.log(person.name); // Sunshine
console.log(person.show());  // 18====女

请看代码后的注释,this指向的都是共有的属性和方法,而直接通过var声明的则属于私有变量(即外部不可访问变量),然后通过一个共有的show方法将私有的age和sex输出。当然show方法也要通过this声明才可以哟,否则的话show方法也是不可访问的。

继承 继承其实就是当多个方法存在相同的属性和方法是,就把这些相同的属性和方法提取到一个公共的方法中,通过原型prototype继承该方法,当然你也可以通过call或apply来继承该方法中的属性和方法。


function Person(name , age , sex){
 this.name = name ; 
 this.age = age ; 
 this.sex = sex ; 
 this.show = function (){
  console.log( this.age + "========"+ this.sex );
 }
}
function Student(name , age , sex , score){
 this.score = score ; 
 Person.apply(this,[name , age , sex]);
}
function Worker(name , age , sex , job){
 this.job = job ; 
 Person.call(this,name , age , sex);
}
Dancer.prototype = new Person('Sunshine',18,'女');
function Dancer(salary ){
 this.salary = salary ;
}
var student = new Student('Sunshine',18,'女',100);
var worker = new Worker('Sunshine',18,'女','IT');
var dancer = new Dancer(20000);
console.log(student);
console.log(worker);
console.log(dancer);

最终的结果如下:

JavaScript面向对象特性概述

当然,个人感觉那个prototype没有说的很好,如果看到这篇博客的你有更好的建议或意见的话,欢迎给我留言。还有call和apply,其实它们的作用是一样的,都是改变this指向,然后它们的区别也可以从代码中看出,传参方式不同。

多态 最后要说多态了,写这篇文章之前,自己对多态还是处于懵逼的状态,查阅了不少其他同行的博客,以及W3C 上的解释,把这些总结了一下,多态就是在执行同一操作且作用于不同对象时,返回不同的结果 。其实也就是把做什么和由谁去做分开,这样使得代码更容易维护,且条例清晰。直接上例子吧:


function dwn(s){
 document.write(s+"<br/>");
}
function Animal(){
 this.bite=function(){
  dwn("animal bite!");
 }
}
function Cat(){
 this.bite=function(){
  dwn("Cat bite!");
 }
}
Cat.prototype=new Animal(); ///inherit Animal
function Dog(){
 this.bite=function(){
  dwn("Dog bite");
 }
} 
Dog.prototype=new Animal(); ///inherit Animal
function AnimalBite(animal){
 if(animal instanceof Animal) //这里是判断animal的原型是否指向Animal
 animal.bite();
}
var cat = new Cat();
var dog = new Dog();
AnimalBite(cat);
AnimalBite(dog);
//最终输出的结果如下:
/*
 Cat bite!
 Dog bite
*/

终于写完了,如果以上有错误的话,欢迎指出~

以上就是Javascript基于对象三大特性,希望对大家的学习有所帮助。

作者最新文章