zoukankan      html  css  js  c++  java
  • 关于js继承学习系列之五:其他方式及总结[转]

          除前文学习的三种继承外,还有另外三种继承模式:原型继承(Prototypal Inheritance)、寄生继承(Parasitic Inheritance)和寄生组合继承(Parasitic Combination Inheritance)。它们都以下面这个函数为前提的

    1 function object(o)
    2 {
    3 function F(){}
    4 F.prototype = o;
    5 return new F();
    6 }


    先是定义F(),它相当于是个模板类,接着它的原型对象被指向了传入的参数o,F具有了o的属性和方法(作为原型属性和方法),最后返回一个模板类实例。 可以看出它的本质是基于对象的继承(新对象继承原对象的属性、方法,或者说是扩展)。object()是原型继承的核心。下面是通过object()进行 原型继承的例子:

     1 var person ={
    2 name : "sds",
    3 friends : ["sds1","sds2"]
    4 };
    5 var other = object(person);
    6 other.showName = function(){return this.name;}
    7 other.showFriends = function(){return this.friends;}
    8 other.name = "sds3";
    9 other.friends.push("sds4");
    10
    11 alert(other.showName());//sds3
    12 alert(other.showFriends());//sds1,sds2,sds4


    从object()定义我知道,other对象的原型是person,即name,friends属性是other的原型对象上的属性,任务对它们的改变都影响到其他对象(从person继承的,甚至person自己),在上面的示例基础上增加下面的代码:

    1 alert(person.name);//sds
    2 alert(person.friends);//sds1,sds2,sds4
    3
    4 var another=object(person);
    5 alert(another.name);//sds
    6 alert(another.friends);//sds1,sds2,sds4


    正如前面所说的,原型属性(如friends)的改变将影响其他对象。寄生继承可以看作是对原型继承的增强,它在object()基础上提供了create(),如下代码

    1 function create(o)
    2 {
    3 var n = object(o);
    4 //定义新对象自己的属性和方法
    5 n.fun1 = function(){alert("Hello World");};
    6
    7 //返回
    8 return n;
    9 }


    create()的用意很明确,相对于object()来说,新对象(通过原型)继承了o的属性、方法后,再定义新对象自己的属性、方法。套用时下最流行的做法:先把别人的照搬来,揉合点自己的,最后拿出去买。绝大部分的国产货就是这样的。
        object()并不是起clone作用的,n和o也是有着区别的,不能把n看作是o的clone副本。
        寄生组合继承,是另一种重要的继承。在yahoo! user interface库中的YAHOO.lang.extend()中使用。它主要是为了解决组合继承效率低的问题,因为组合继承中,会运行两次基类构造器。寄生组合继承核心代码是

    1 function inherit(childType,baseType){//childType:子类构造器,baseType:基类构造器
    2 var proto = object(baseType.prototype);//基于基类原型对象创建一个对象,将作为子类原型对象
    3 proto.constructor = childType;//指定新原型对象的构造器属性为子类构造器
    4 childType.prototype = proto;//子类原型属性指向新的原型对象
    5 }


    inherit()实现了寄生组合继承的重要一个环节。注意这里只实现了对基类原型的继承。完整的实现可以参考如下代码:

     1 function baseClass(name)
    2 {
    3 this.name = name;
    4 this.colors = ["red","blue"];
    5 }
    6 baseClass.prototype.getName = function(){return this.name;};
    7
    8 function childClass(name,age)
    9 {
    10 baseClass.call(this,name);
    11 this.age = age;
    12 }
    13 inherit(childClass,baseClass);
    14 childClass.prototype.getAge = function(){return this.age;};//这句一定要放在inherit()之后,因inherit()会改变childClass.prototype的指向
    15
    16 var obj = new childClass("sds",50);
    17 alert(obj.getName());//sds
    18 alert(obj.getAge());//50
    19 alert(obj.colors);//red,blue;


    这样,寄生组合继承的实现效率要比组合继承高。原因是它不再new一个父类实例作为子类原型对象。

    关于对象的clone,我认为可以参考下面的代码:

    1 function clone(o)
    2 {
    3 var obj ={};
    4 for(var p in o)
    5 {
    6 obj[p] = o[p];
    7 }
    8 return obj;
    9 }


    另关于原型对象上的属性有必要强调一点,对象的原型对象上的属性并不是对象的属性,但是对象可以访问(通过.或[])。in操作符可以访问对象上所有能访问的属性和方法。而hasOwnProperty()方法只能检测对象自身的属性和方法。考虑如下代码

    1 var one = {"name":"sds","getName":function(){return this.name;}};
    2 var two = object(one);//object()来自于前面的示例
    3 alert("name" in two);//true
    4 alert(two.hasOwnProperty("name"));//false;
    5 two.name = "sds1";
    6 alert(two.hasOwnProperty("name"));//true;


    注意:在对two.name赋值操作后,two对象自身上会创建一个属性name,它有别于two的原型对象上的name属性,从此对two.name的 访问或赋值都将使用它自己的name属性,而原来位于原型上的name将束置高阁,闲置不用。这点在我们进行面向对象的js编程时要注意的,即在给对象的 原型上的属性赋值操作,会使对象本身添加同名属性,从而覆盖原型属性。

  • 相关阅读:
    Bootstrap模态框modal的高度和宽度设置
    入门学习Linux常用必会命令实例详解
    Linux 系统中用户切换(su user与 su
    hdu 3549 Flow Problem(最大流模板题)
    第三章 学后心得及总结 【物联网1132-11】
    Find Minimum in Rotated Sorted Array 旋转数组中找最小值 @LeetCode
    面试题4
    Fp关联规则算法计算置信度及MapReduce实现思路
    POJ 1679 The Unique MST 推断最小生成树是否唯一
    论程序猿的社会地位
  • 原文地址:https://www.cnblogs.com/405464904/p/2179585.html
Copyright © 2011-2022 走看看