对象冒充,apply()方法 ,Call()方法 ,原型链(利用prototype对象来实现.)
Javaspript的继承
} JavaScript中的继承
特点:
1、ECMAScript中并没有像其他语言那样严格地定义抽象类.
2、所有类的方法都是public的作用域
3、继承的方式不止一种,支持多重继承
严格讲,javascript的继承机制并不是明确规定的,而是通过模仿实现的。
对象冒充
其原理如下:构造函数使用this关键字给所有属性和方法赋值.因为构造函数只是一个函数,所以可使用ClassA的构造函数成为ClassB的方法,然后调用它.ClassB就会收到ClassA的构造函数中定义的属性和方法.
eg1:
function ClassA(sColor){
this.color = sColor;
this.sayColor = function(){
alert(this.color); } }
function ClassB(sColor){
this.newMethod = ClassA;//定义新的属性指向classA
this.newMethod(sColor);
delete this.newMethod; 把这个属性删除掉,相当于classB从classA继承
}
注意:所有的新属性和新方法都必须在删除了新方法的代码行后定义.否则,可能会覆盖超类的相关属性和方法.
function ClassA(sColor){
this.color = sColor;
this.sayColor = function(){
alert(this.color); } }
function ClassB(sColor,sName){
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.name = sName;//定义新方法新属性需要先删除覆盖过来的超类
this.sayName = function(){
alert(this.name); }}
//call
Var objA = new ClassA(“red”); Var objB = new ClassB(“blue”,”zhang”);
objA.sayColor(); //output “red”;
objB.sayColor(); //output “blue”;
objB.sayName(); //output “zhang”;
模仿多重继承
eg:
function ClassA(sColor) function ClassB(sName){
{ this.name = sName;
this.color = sColor; this.sayName=function()
this.sayColor=function() { alert(this.name); }}
{
alert(this.color);
}
}
function ClassC(sColor,sName,sModel){ //classC希望从A和B继承
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.newMethod =ClassB;
this.newMethod(sName);
delete this.newMethod;
this.model=sModel;
this.sayModel = function()
{
alert(this.model);
}
}
//call
var cObj = new ClassC("red","zhang","T40");
cObj.sayColor(); //output “red”
cObj.sayName(); //output “zhang”;
cObj.sayModel(); //output “T40”;
注意:多重继承防止出现父类同名问题
由于这种方式的流行,ECMAScript的第三版为Function对象加入了两个新方法 Call()和apply()
2、Call()方法
call方法是与经典的对象冒充方法最相似的方法.它的第一个参数用作this的对象,其他参数都直接传递给函数自身.
eg:
function sayColor(sprev,snext)
{
alert(sprev+this.color+snext); //有this说明肯定有对象来调用它
}
var obj = new Object();
obj.color = “red”;
sayColor.call(obj,”The color is ”,”a very nice color”);会把obj对象传给saycolor的this参数
//output “The color is red ,a very nice color”
利用call关键字实现继承
function ClassA(sColor){
this.color = sColor;
this.sayColor=function(){
alert(this.color); }}
function ClassB(sColor,sName) {
// this.newMethod=ClassA;
// this.newMethod(sColor);
// delete this.newMethod;
ClassA.call(this,sColor);
//调用calssA这个函数,传递对象是当前对象本身,并把参数传进去
this.name = sName;
this.sayName= function(){
alert(this.name); }}
//call
var objB = new ClassB(“red”,”zhang”);
objB.sayColor(); //output “red”
objB.sayName(); //output “zhang”
} apply()方法
apply()方法有两个参数,用作this的对象和要传递给函数的参数的数组.
eg:
function sayColor(sprev,snext){
alert(sprev+this.color+snext);}
var obj = new Object();
obj.color =“red”;
sayColor.apply(obj,new Array(“The Color is “,” a very nice color”));第二个参数用数组表示,然后根据数量一一传递给调用函数//output “The color is red ,a very nice color”
利用apply关键字实现继承
function ClassA(sColor){
this.color = sColor;
this.sayColor=function(){
alert(this.color);}}}
function ClassB(sColor,sName){
// this.newMethod=ClassA;
// this.newMethod(sColor);
// delete this.newMethod;
ClassA.apply(this,new Array(sColor));
this.name = sName;
this.sayName= function(){
alert(this.name); }}
//call
var objB = new ClassB(“red”,”zhang”);
objB.sayColor(); //output “red”
objB.sayName(); //output “zhang”
原型链
利用prototype对象来实现.
function ClassA(){
}
ClassA.prototype.color = “red”;
ClassA.prototype.sayColor = function(){
alert(this.color);
}
function ClassB(){
}
ClassB.prototype = new ClassA //classB从classA继承
} 注意,调用ClassA的构造函数时,没有给它传递参数.这在原型链中是标准做法,要确保构造函数没有任何参数.
} 另:与对象冒充相似,子类的所有属性和方法都必须出现在prototype属性补赋值后,因为在它之前赋值的所有方法都会被删除.
eg:
function ClassB(){ //子类不能存在构造函数,否则会被classA替换掉
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = “”;
ClassB.prototype.sayName = function(){
alert(this.name);
}
//call
var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "yellow";
objB.name = "zhang";
objA.sayColor(); //output “blue”
objB.sayColor(); //output “yellow”;
objB.sayName(); //output “zhang”
原型链的弊端在不支持多重继承.记住,原型链会用另一类型的对象重写类的prototype属性
混合模式
用构造函数方式定义属性,用原型方式定义方法.这种方式同样适用于继承机制.
eg:
//ClassA
function ClassA(sColor)
{
this.color = sColor;
}
ClassA.prototype.sayColor = function(){
alert(this.color);
}
//ClassB
function ClassB(sColor,sName){
ClassA.call(this,sColor);
this.name = sName;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function(){//自己的方法sayName
alert(this.name);
}
//call
var objA = new ClassA(“red”);
var objB = new ClassB(“blue”,”zhang”);
objA.sayColor(); //output “red”
objB.sayColor(); //output “blue” ,b没有sayColor方法 是从A继承的
objB.sayName(); //output “zhang”
一个更实际的例子
//创建基类(多边形)
function Polygon(iSides){
this.sides = iSides;
}
Polygon.prototype.getArea=function(){ //原型链方法用来被继承或被重写
return 0;
}
//创建子类(三角形)
function Triangle(iBase,iHeight){
Polygon.call(this,3);//通过继承方式设定他3个边
this.base = iBase;
this.height = iHeight;
}
Triangle.prototype = new Polygon();// 继承弗雷方法
Triangle.prototype.getArea = function()//重写了计算面积方法
{
return this.base*this.height/2;
}
//创建子类(四边形)
function Rectangle(iLength,iWidth){
Polygon.call(this,4);
this.length = iLength;
this.width = iWidth;
}
Rectangle.prototype = new Polygon();
Rectangle.prototype.getArea = function()
{
return this.length*this.width;
}
//调用
var triangle = new Triangle(12,4);
var rectangle = new Rectangle(22,10);
alert(triangle.sides); //output “3”
alert(triangle.getArea()); //output “24”
alert(rectangle.sides); //output “4”;
alert(rectangle.getArea()); //output “220”
多态
//Class Parent
function Person(skin,language)//肤色 语言
{
this.skin = skin;
this.language = language;
}
Person.prototype.SayHellow = function(){}
//中国人--子类
function China(skin,language,name)
{
Person.call(this,skin,language);//继承父类属性
this.name = name;
this.SayName = function()
{
alert(this.name);
}
}
China.prototype = new Person();//继承父类原型链方法
China.prototype.SayHellow = function()
{
alert("您好");
}
//美国人 --子类
function American(skin,language)
{
Person.call(this,skin,language);
}
American.prototype = new Person();
American.prototype.SayHellow = function()
{
alert("hellow");
}
function SayHellow(p)//多态
{
p.SayHellow();
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<input type="button" value="中国人的问候" onclick ="SayHellow(new China('黄色','汉语','张三'))"/> <input type="button" value = "美国人的问候" onclick="SayHellow(new American('白色','英语'))"/>
} </BODY>