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>
PS:JS封装只有两种状态,一种是公开的,一种是私有的。
通过构造函数添加成员方法和通过原型法添加成员方法的区别
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函数是无态的,支持任意长度,类型的参数列表。如果同时定义了多个同名函数,则以最后一个函数为准。
案例: