Pro JavaScript Techniques 笔记.part.3.1.3 类式继承 —— 构建基类

上篇解决了之前的继承中调用uber()的一些问题,此篇可以封装上篇篇尾所述的一些缺陷。声明函数部分是无法封装的。

var create = function () {
    var X = function () {};
    X.inherits(Base);
    return X;
};

通过这个函数获得的构造函数都是同一个。但可以封装剩下两步骤,并构建自己的基类型。
尽管都指向的是函数中的引用,构造函数的名称也都是X,但永远不会是同一个。真是有点无地自容。

// 命名空间
var X = {};
// 提供对象扩展方法
X.extend = function (target, source) {
    var i = '';
    for (i in source) {
        if ( source.hasOwnProperty(i) ) {
            target[i] = source[i];
        }
    }
    return target;
};

// 基类
X.Base = function () {};
X.Base.baseMethods = {
    // 此处指定必须拥有的方法
    log : function () {
        console.log('Hey,');
    }
};

X.Base.prototype = X.extend({
    // 其他属性和方法
}, X.Base.baseMethods);

Function.method('extendFrom', function (Parent, obj) {
    this.inherits(Parent);
    // 强制设置必须拥有的方法 当然最好可以靠约定 不过约定有时并不可靠
    X.extend(this.prototype, X.Base.baseMethods);
    X.extend(this.prototype, obj);
    return this;
});

测试:

X.A = function () {};
X.B = function () {};
X.C = function () {};

X.A.extendFrom(X.Base, {
    log : function () {
        this.uber('log');
        console.log('What\'s');
    }
});
X.B.extendFrom(X.A, {
    log : function () {
        this.uber('log');
        console.log('up');
    }
});
X.C.extendFrom(X.B, {
    log : function () {
        this.uber('log');
        console.log('!');
    }
});

( new X.C() ).log();

// 或者在项目中 可以这样
window.pageData = {
    pageId : 'C'
};
X.init = function () {
    ( new X[window.pageData.pageId] () ).log();
};
X.init();