封装、继承、多态是面向对象的三大基本特征,而javascript做为一种面向对象的语言既javascript可以称得上是一种面向对象的程序语言那么它也就必然具有这三个特征。javascript的最初设计者觉得这种语言只要能够完成一些简单操作就够了,没必要设计得很复杂。作为一种简易的脚本语言,javascript在封装、继承、多态上并没有给出一种统一的规范,它不像java那样将属性、方法封装到类中,通过各种方法实现了继承跟多态,对于语言的使用人员来说只要能按照规则去做去使用即可。javascript在这些方面相当的灵活,不管是在类跟对象的创建方面还是在实现继承跟多态方面供开发人员实现的方式有很多,在使用上就体现出了javascript的随意性跟灵活性。
在上一篇博客中主要介绍了一下javascript中类跟对象的封装,javascript在继承方面跟封装一样有很多可选的方案,而且继承的实现跟封装紧密相连不可分割。
对象冒充
function Cat(name) //构造函数封装父类对象
{
this.name=name;//name属性
this.sayHello=function()
{
alert("喵喵!");
}
}
function BlackCat(name)//子类通过冒充父类对象实现对父类的继承
{
this.newmethod=Cat;//冒充父类对象
this.newmethod(name);//完成初始化
delete this.newmethod;//删除newmethod方法
}
var blackcat=new BlackCat("black");//实例化子类对象
alert(blackcat.name); //输出black
blackcat.sayHello();//子类方法调用 输出“喵喵!”
call方法
javascript的开发人员在对象的冒充上有了新的启发即可以通过调用父类的构造方法完全可以实现对父类的继承,在javascript中提供了call方法用来完成对对象的初始化。
function sayHello(name)
{
this.name=name;
}
var cat=new object();
sayHello.call(cat,"猫");//通过call函数调用sayHello时,sayHello函数中的this指代call函数提供的第一个参数(一般为对象)
使用call函数完成继承:
function WhiteCat(name,age)//子类通过call函数完成对父类的继承
{
Cat.call(this,name);//通过call函数调用父类构造函数this为WhiteCat对象
this.age=age;
this.sayAge=function()
{
alert(this.age);
}
}
var whitecat=new WhiteCat("white",12);//实例化子类 alert(whitecat.name); whitecat.sayHello(); whitecat.sayAge();
apply方法
与call函数原理一样,当构造函数有足够多的参数时,为了方便子类调用父类构造函数时参数的传递,javascript提供了apply方法可以将子类的参数通过arguments对象一次性传递给父类构造函数。
function WhiteCat(name,age)//子类通过call函数完成对父类的继承
{
Cat.apply(this,arguments);//通过call函数调用父类构造函数this为WhiteCat对象
this.age=age;
this.sayAge=function()
{
alert(this.age);
}
}
原型链方法
function Dog()//原型法封装父类
{
}
Dog.prototype.name="dog";
Dog.prototype.sayHello=function()
{
alert("汪汪!");
}
function BlackDog()//原型链发实现对父类的继承
{
}
BlackDog.prototype=new Dog();
var blackdog=new BlackDog();
alert(blackdog.name);
blackdog.sayHello();
混合式方法
function People(name)//利用构造函数/原型混合式方法封装父类对象
{
this.name=name;
}
People.prototype.sayHello=function()
{
alert("hello word!");
}
function Student(name){ //混合式方法实现继承
People.call(this,name);//call方法继承属性
}
Student.prototype=new People();//原型方法继承方法
var st=new Student("liming ");
alert(st.name);
st.sayHello();
总结
javascript在继承实现上,大致可分为三类,构造函数方法(对象冒充、call方法、apply方法)、原型方法、混合式方法(原型/构造函数方法),每一种继承方式都对应着一种封装方式,可以说没有封装就没有继承。构造函数式带来的主要问题是所有的同类对象都不共享方法都有自己的方法,而原型方法主要问题构造函数不能有参数即不可以在实例化对象时对对象进行初始化,并且当对象属性不为基本变量时所有对象共享同一属性,而解决这两个问题的最好方法就是联合使用构造函数和原型方法。继承作为面向对象语言三大特征之一,最伟大之处就是实现了代码的复用,javascript虽然做得不是很好,但更多的是提现出设计者设计javascript脚本语言的初衷:简单、灵活、随意、易于使用。