《JavaScript語言精粹》之函數化

寫在前面

看到好多書評和讀書筆記都說《JavaScript語言精粹》字字珠璣,名不虛傳。。固然,要看得懂才行javascript

其實我的認爲函數化部分不是很好,舉的例子不是十分恰當,以前看不懂是由於被成功誤導了,就像《Head First》設計模式第一章《策略模式》同樣,做者有些偏離章節主題,讀者容易被誤導html

聲明:姑且把函數化部分給出的用來建立對象的函數稱爲「創造函數」吧,爲了與「構造函數」區分開。。不是很好聽,將就着用吧java

一.源碼中須要注意的點

很容易就能拿到源碼,和中文版書上的代碼同樣,仔細看了一遍發現了一個很精妙的地方,固然,不是很好理解設計模式

P.S.源碼有點小問題:「創造函數」cat花括號不匹配,中文版54頁,return that;以前少了};安全

Object的原型函數superior內部有一個很精妙的地方

Object.method('superior', function (name) {
    var that = this,
        method = that[name];
    return function (  ) {
        return method.apply(that, arguments);
    };
});

亮點就是最後一句的arguments,看似無意,實際上是有意爲之的,代表用superior調用父類方法時也能夠傳參。固然,傳參的話須要修改調用方式,測試代碼以下:app

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

var mammal = function (spec) {
    var that = {};

    that.get_name = function (  ) {
        return spec.name;
    };

    that.says = function (  ) {
        return spec.saying || '';
    };

    return that;
};

var cat = function (spec) {
    spec.saying = spec.saying || 'meow';
    var that = mammal(spec);
    that.purr = function (n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    };
    that.get_name = function (  ) {
        alert("cat.get_name :" + arguments.length);///
        return that.says(  ) + ' ' + spec.name +
                ' ' + that.says(  ) + "[" + arguments.length + "]";
    };

    return that;
};

Object.method('superior', function (name) {
    var that = this,
        method = that[name];
    return function (  ) {
        alert("superior :" + arguments.length);///
        return method.apply(that, arguments);
    };
});

var coolcat = function (spec) {
    var that = cat(spec),
        super_get_name = that.superior('get_name');
    that.get_name = function () {
        alert("coolcat.get_name :" + arguments.length);///
        return 'like ' + super_get_name.apply(this, arguments) + ' baby';
    };
    return that;
};

var myCoolCat = coolcat({name: 'Bix'});
var name = myCoolCat.get_name(1, 2, 3);
//        'like meow Bix meow baby'


alert(name);    // 'like meow Bix meow[3] baby'

P.S.開始覺得superior函數最後的arguments是做者的錯誤,以爲應該須要把外面的arguments對象傳給method而不是裏面的,繞了一大圈發現是本身錯了,道行不夠,沒能秒懂道格拉斯大爺的意思。。函數

二.函數化的初衷

函數化部分開篇就說明了初衷:爲了實現私有屬性,建立最後提到的「防僞對象」學習

目的無可厚非,實現私有屬性太有必要了。但舉的例子mammal -> cat -> coolcat太不合適了,做者想說明用函數化的方式能夠實現繼承測試

固然,不是嚴格意義上的繼承,由於函數化方式沒有用到自定義類型,子類實例與父類實例的is-a關係也就無從談起了this

P.S.看第一遍的時候cat的例子就把我帶到溝裏去了,覺得函數化就是要拋棄new,徹底用函數來實現繼承。。天然是在溝裏越走越深了

三.函數化的思想

直接看代碼,代碼本身會說話:

/*
 * 函數化的思想:
 * 1.建立對象
 * 2.添加私有屬性
 * 3.公開接口(添加公有屬性)
 * 4.返回該對象
 */
/*
 * method: getSuper
 * @param spec 規格說明對象,提供建立對象所需的基本數據
 * @param my 「創造函數」之間共享數據的容器
 */
function getSuper(spec, my){
    var obj;            // 要返回的對象
    var my = my || {};  // 沒傳入就建立一個

    // 私有屬性
    var attr = spec.value;  // 從規格說明對象取數據
    var fun = function(){
        alert(attr);
    }

    // [可選]把須要與其它「創造函數」共享的數據裝入my

    // 建立對象,能夠用任意方式,好比new、字面量、調用其它「創造函數」 
    obj = {
        name: "SuperObject"
    };

    // 公開接口
    obj.fun1 = fun;

    // 返回obj
    return obj;
}

/*
 * method: getSub
 * 參數同上
 */
function getSub(spec, my){
    var obj;
    var my = my || {};

    // 私有屬性
    var attr = spec.value + 1;
    var fun = function(){
        alert(attr);
    }

    // [可選]共享

    // 建立對象
    obj = getSuper(spec, my);   // 能夠直接傳過去,固然也能夠改一改再傳,或者傳別的什麼

    // 公開接口
    obj.fun2 = fun;

    // 返回obj
    return obj;
}

// 測試
var spec = {
    value: 1
};
var sub = getSub(spec); // 不用傳入my,my只應該在「創造函數」之間用
sub.fun1(); // 1
sub.fun2(); // 2

P.S.又是「建立對象 -> 加強 -> 返回新對象」這個套路,不就是尼古拉斯所說的由道格拉斯發明的「模塊模式」嗎?

四.防僞對象(持久性的對象)

函數化部分的核心就是它了,注意上面例子中公開接口的方式:

// 私有屬性
var myFun = function(){/* ... */};
// 公開接口
obj.fun = myFun;

而不直接用:

// 公開接口
obj.fun = function(){/* ... */};

第一種方式更安全,由於即使從外界修改了fun,內部其它調用了myFun的方法仍然能夠正常工做,這樣的函數對象就是所謂的防僞對象

完整定義:

防僞對象的屬性能夠被替換或者刪除,但該對象的完整性不會受到損害

也被稱爲持久性的對象,一個持久性對象就是一個簡單功能函數的集合

後話

到這裏《JavaScript語言精粹》的學習筆記就告一段落了,補好了[函數化]的空缺,學習筆記的其它部分請查看黯羽輕揚:《JavaScript語言精粹》學習筆記

相關文章
相關標籤/搜索