关于js继承---Base类的源码解析

本文深入剖析了Base2.js库中的继承实现机制,详细解释了如何使用Base类进行对象继承,包括构造函数、原型链及方法重写等方面的内容。
 
   Base据说是最好的js继承的封装类,最近读了一下base2.js的继承部分,现在将源码的解析贴下,有错误的地方希望大家指出,我会更新的.

  1. // timestamp: Tue, 01 May 2007 19:13:00
  2. /*
  3.  base2.js - copyright 2007, Dean Edwards
  4.  http://www.opensource.org/licenses/mit-license
  5.  */
  6. // You know, writing a javascript library is awfully time consuming.
  7. ////////////////////  BEGIN: CLOSURE  ////////////////////
  8. // =========================================================================
  9. // base2/Base.js
  10. // =========================================================================
  11. // version 1.1
  12. var Base = function(){
  13.     // call this method from any other method to invoke that method's ancestor
  14. };
  15. Base.prototype = {
  16.     extend: function(source){
  17.         //参数大于一个时
  18.         if (arguments.length > 1) { // extending with a name/value pair
  19.             //获得proto的祖先
  20.             var ancestor = this[source];
  21.             var value = arguments[1];
  22.             //如果value(第二个参数)是function,并且祖先对象存在,在重载函数中调用base时
  23.             if (typeof value == "function" && ancestor && //bbase/b/.test(value)) {
  24.                 // get the underlying method
  25.                 var method = value;
  26.                 // override
  27.                 value = function(){
  28.                     var previous = this.base;
  29.                     this.base = ancestor;
  30.                     //上溯到父类对象
  31.                     var returnValue = method.apply(this, arguments);
  32.                     this.base = previous;
  33.                     return returnValue;
  34.                 };
  35.                 value.method = method;
  36.                 value.ancestor = ancestor;
  37.             }
  38.             this[source] = value;
  39.         }
  40.         else 
  41.             if (source) { // extending with an object literal 用一个对象列表来扩展
  42.                 var extend = Base.prototype.extend;
  43.                 /**
  44.                  *   1.扩展原型方法和属性 2.
  45.                  */
  46.                 //如果是扩展属于原型的方法或属性,先遍历其重载Object的3个方法
  47.                 if (Base._prototyping) {
  48.                     var key, i = 0, members = ["constructor""toString""valueOf"];
  49.                     while (key = members[i++]) {
  50.                         //如果是重载了这些方法
  51.                         if (source[key] != Object.prototype[key]) {
  52.                             /**
  53.                              * 逐个扩展,用call的原因是要将extend的上下文改为要扩展的源this,
  54.                              * 既是新建对象的父类对象
  55.                              */
  56.                             extend.call(this, key, source[key]);
  57.                         }
  58.                     }
  59.                 }
  60.                 else 
  61.                     if (typeof this != "function") {
  62.                         // if the object has a customised extend() method then use it
  63.                         extend = this.extend || extend;
  64.                     }
  65.                 // copy each of the source object's properties to this object
  66.                 for (key in source)
  67.                     if (!Object.prototype[key]) {
  68.                         extend.call(this, key, source[key]);
  69.                     }
  70.             }
  71.         return this;
  72.     },
  73.     
  74.     base: Base
  75. };
  76. Base.extend = function(_instance, _static){ // subclass
  77.     /**
  78.      * Base类原型的扩展别名,将这个当成一个方法调用
  79.      */
  80.     var extend = Base.prototype.extend;
  81.     /**
  82.      * build the prototype,创建原型
  83.      * 设置原型标志
  84.      */
  85.     Base._prototyping = true;
  86.     /**
  87.      * 创建一个Base的实例,初始化继承部分
  88.      * 继承方式大致还是以下方式
  89.      * function A(){}
  90.      * function B(){
  91.      *     this.b=[];
  92.      * }
  93.      * A.prototype=new B();//A继承B的所有属性和方法
  94.      * 这种继承方式会有一个问题,B中声明的对象(如b)以prototype的形式
  95.      * 被A继承之后,prototype只是生成一个指向B中对象的引用,即
  96.      * A所有实例会共同享有B中对象(b)
  97.      * var a1=new A();
  98.      * var a2=new A();
  99.      * a1.b.push("a11");
  100.      * a2.b.push("a21");
  101.      * 此时,a1.b=a2.b=["a11","a21"],
  102.      *
  103.      * Dean Edwards在实现继承的时候,以父类为基础,创建实例,
  104.      * 利用extend扩展该实例,最后用A.prototype=new B();实现继承
  105.      * 但是属性是对象的时候没有做处理,
  106.      * 还是没有避开上述的继承缺陷
  107.      */
  108.     var proto=new this;
  109.     /**
  110.      * 在这里,不可以用 proto.extend(_instance)代替
  111.      */
  112.     extend.call(proto, _instance);
  113.     /**
  114.      * 类实例属性和方法的原型部分构造完毕,删除标志位
  115.      */
  116.     delete Base._prototyping;
  117.     
  118.     /**
  119.      * 这里作者运用了适配器的模式,用自定义的构造器生成一个新的类对象
  120.      * wrapper/adapter:通过一定的方法,一个对象封装或授权另一个
  121.      * 对象来改变它的接口或者行为
  122.      */
  123.     // create the wrapper for the constructor function
  124.     /**
  125.      *  获得构造器的引用
  126.      */
  127.     var constructor = proto.constructor;
  128.     /**
  129.      * 建立klass的Function对象,调用自定义的构造器, klass就是衍生的子类
  130.      * 两种情况下,调用此方法:
  131.      * 1.创建类实例的时候,这时候不是原型构造阶段,执行由extend方法
  132.      * 继承的时候设定的构造方法
  133.      * 2.当用extend方法衍生子类的时候---new this
  134.      * 因为下文中klass的属性已经全部获得,
  135.      * 所以当new完之后,获得所有父类的方法和属性都包含在了
  136.      * proto里面了,这时候,在proto的基础上运用prototype的extend方法
  137.      * 将此子类的属性和方法添加到proto里面
  138.      */
  139.     var klass = proto.constructor = function(){
  140.         /**
  141.          * var proto=new this; 调用父类的构造函数,创建一个父类的实例
  142.          * new this用完后,函数重定向到子类对象构造方法
  143.          */
  144.         if (!Base._prototyping) {
  145.             /**
  146.              * 当在构造函数中(constructor)调用base方法时,
  147.              * base方法会调用父类对象的构造函数,这时候会嵌套
  148.              * 调用这个代码段,方法得以执行的条件就是this._constructing==true
  149.              */
  150.             if (this._constructing || this.constructor == klass) { // instantiation
  151.                 this._constructing = true;
  152.                 constructor.apply(this, arguments);
  153.                 delete this._constructing;
  154.             }
  155.             /**
  156.              * 
  157.              * 不再向下执行
  158.              */
  159.             else { // casting
  160.                 var object = arguments[0];
  161.                 if (object != null) {
  162.                     (object.extend || extend).call(object, proto);
  163.                 }
  164.                 return object;
  165.             }
  166.         }
  167.     };
  168.     
  169.     // build the class interface
  170.     /**
  171.      * 
  172.      */
  173.     for (var i in Base){
  174.         klass[i] = this[i];
  175.     }
  176.     /**
  177.      * 创建继承链
  178.       */
  179.     klass.ancestor = this;
  180.     klass.base = Base.base;
  181.     klass.prototype = proto;
  182.     klass.toString = this.toString;
  183.     /**
  184.      * 扩展类方法,属性,类似java的static
  185.      */
  186.     extend.call(klass, _static);
  187.     
  188.     // class initialisation   如果存在init函数 调用
  189.     if (typeof klass.init == "function"
  190.         klass.init();
  191.     return klass;
  192. };
  193. // initialise
  194. Base = Base.extend({
  195.     constructor: function(){
  196.         this.extend(arguments[0]);
  197.     }
  198. }, {
  199.     ancestor: Object,
  200.     base: Base,
  201.     
  202.     implement: function(_interface){
  203.         if (typeof _interface == "function") {
  204.             // if it's a function, call it
  205.             _interface(this.prototype);
  206.         }
  207.         else {
  208.             // add the interface using the extend() method
  209.             this.prototype.extend(_interface);
  210.         }
  211.         return this;
  212.     }
  213. });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值