首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

javascript_种_继承_小结

2012-10-09 
javascript_类_继承_小结javascript的类继承小结?继承这个东西,本来是面向对象的特性。javascript本来也不

javascript_类_继承_小结

javascript的类继承小结

?

继承这个东西,本来是面向对象的特性。javascript本来也不是为面向对象设计的,起码初衷不是,否则也不会没有用class这个关键字(ECMAScript保留了这个关键字)。

作为面向对象的“弥补”,跟perl一个样子,留下一个继承的“基因”,或者叫“继承通道”更合适,名为prototype,在本scope中没有找到某个方法时,会去prototype中查找,以此一直往上一层找下去,直到找到或者到达顶层类。看出来了,javascript的这种寻找方式是“单继承的”。perl中的这个“继承通道”名为@ISA,@符号表明这是个数组,可以支持多继承。

原型链_单继承

?

原理:

javascript中这个“继承通道”的官方说法叫“原型链”(prototype chain),即在子类找不到某属性时,会去原型链中寻找。

注意:

#1 原型链是单继承的

#2 父类构造函数可以有参数,但是子类调用时传递给父类的参数没有用,所以标准做法是不传递参数(传也可以但不起作用,反而容易让人误解)

#3 子类在给prototype赋值前不要定义属性,否则会被抛弃(其实是指针重定向)

#4 子类给prototype赋值为一个对象,而不是一个类(与perl等不同)

?

不足之处:

仅仅可以继承prototype中的属性(方法是对象,也是属性),而this属性并不能继承。

?

        function ClassA() {            this.age = 100;            function sayAge(){                alert("age:" + this.age);            }        }        ClassA.prototype.color = "red";        ClassA.prototype.name = "fantaxy_a";        ClassA.prototype.sayColor = function () {            alert("color:" + this.color);        };        ClassA.prototype.sayName = function(){            alert("name:" + this.name)        }        function ClassB() {            this.name = "fantaxy_b"        }        ClassB.prototype = new ClassA();        ClassB.prototype.sayName = function(){            alert("My name is:" + this.name)        }        //run        b = new ClassB()        b.sayColor() // =>red        b.sayName() // =>My name is:fantaxy_b        //b.sayAge();//Wrong!!! no this method

?


对象冒充_多继承

原理:

I: 因为父类的类定义即构造函数是个函数,函数是对象,所以可以成为子类的方法被调用

II:又因为父类的属性是通过this关键字设置的,所以子类调用这个函数时,this在子类中执行同样的代码,为子类设置了同样的属性,达到冒充的目标

注意:

#1 冒充可以多继承(多冒充几个父类)

#2 冒充的是父类的this属性(而不是prototype属性)

#3 冒充时,子类属性需要在调用冒充的代码之后写。否则会因为“同名覆盖原则”导致子类属性被父类属性覆盖(正常应该是子类属性覆盖父类属性

#4 冒充多继承时,如果父类有同名方法,由“同名覆盖原则”,后“冒充”的父类方法会被找到执行

?

不足之处:

?

仅仅可以继承this属性,而原型链中的属性并不能继承。

?

        function ClassA(sColor, sName) {            this.color = sColor;            this.name = sName;            this.sayColor = function () {                alert(this.color);            };            this.sayName = function(){                alert(this.name)            }        }        function ClassB(sColor, sName) {            this.newMethod = ClassA;            this.newMethod(sColor, sName);            delete this.newMethod;            //We can define attribute local            this.name = "name is:" + sName;            this.sayName = function(){                alert("My " + this.name)            }        }        //run        b = new ClassB("red", "fantaxy_b");        b.sayColor();// =>red        b.sayName();// =>My name is fantaxy_b
?

对象冒充的同名方法 call() 和 apply()

对象冒充的本质原理为:执行父类的构造方法,利用this原理,设置子类同样的属性。

所以,只要是能在子类中执行父类构造方法的,都可以达到这个效果。

?

call语法:

aMethod.call(objX, paramA, paramB)

等价于在objX这个对象上执行aMethod方法,即:objX.aMethod(paramA, paramB)

如果aMethod为父类构造函数,则达到冒充效果

?

apply语法:与call语法类似,区别在于apply的参数要写进一个Array中,把这个Array作为参数

aMethod.call(objX, [paramA, paramB])

等价于在objX这个对象上执行aMethod方法,即:objX.aMethod([paramA, paramB])

如果aMethod为父类构造函数,则达到冒充效果

?

         function sayColor(sPrefix, sSuffix) {            alert(sPrefix + this.color + sSuffix);        }        var obj = new Object();        obj.color = "red";        //outputs "The color is red, a very nice color indeed. "        sayColor.call(obj, "The color is ", ", a very nice color indeed. ");    //call         sayColor.apply(obj, ["The color is ", ", a very nice color indeed. "]);//apply
?

如果aMethod为父类构造函数,则达到冒充效果

function ClassB(sColor, sName) {      //this.newMethod = ClassA;      //this.newMethod(sColor, sName);      //delete this.newMethod;      ClassA.call(this, sColor);  //call    ClassA.call(this, [sColor]);//apply      //We can define attribute local      this.name = "name is:" + sName;      this.sayName = function(){          alert("My " + this.name)      }  }  

?

原型链和对象冒充混合方式

?

原型链和对象冒充正好是互补的,混合使用,可以达到不错的效果~

?

        function ClassA(sColor) {            this.color = sColor;        }        ClassA.prototype.sayColor = function () {            alert(this.color);        };        function ClassB(sColor, sName) {            ClassA.call(this, sColor);            this.name = sName;        }        ClassB.prototype = new ClassA(null);//这里可以传参数,也可以不传,总之这参数不起作用        ClassB.prototype.sayName = function () {            alert(this.name);        };        //run        b = new ClassB("red", "fantaxy_b");        b.sayColor();        b.sayName();
?

?

?

P

P

P

O

P

P

P

?

热点排行
Bad Request.