Javascript 元編程初探 [1]

引子

元編程會有以下的定義:javascript

一種計算機程序的編寫方式,它能夠將其它程序(或者其自己)做爲數據進行編寫和操做,或者在編譯時作一部分工做,在運行的時候作另一部分工做。

在這裏講到的不少也許只和程序對於工做機制的操做有關,可是做爲初探也許也就足夠了。 鑑於我也是邊學邊寫的這篇文章,若是有謬誤之處,還請指出。java

建立帶有默認參數的函數

function repeat(func, times) {
    times = (Object.prototype.toString.call(times) === '[object Undefined]')?1:times;
    for(var i = 0; i < times; i++){
        func();
    }
}

在函數中使用 Object.prototype.toString.call(times) 是爲了解決 javascript 判斷值爲空的問題,使用這種寫法纔會比較的安全。通常狀況下 false, 0, undefined, null 還有 空字符串 都會被判斷成 false。編程

建立自優化的行數

在瀏覽器的實現上會有許多的不一樣,有時候就須要使用分支。通常狀況下都是監測須要調用的對象或者屬性是否存在,進而進行下一步的操做,像下面的同樣:瀏覽器

function addEvent(elem, type, func){
    if (document.addEventListener) {
        elem.addEventListener(type, func);
    } else {
        elem.attachEvent(type, func);
    }
}

雖然這段代碼可能還有不少其它的問題,可是這段代碼每次在執行時都會進行一次判斷,然而理論上應該能夠作到只在第一次運行的時候進行判斷: 當第一次調用的時候,針對特定的瀏覽器去將本身重寫成另外的一個版本安全

function newAddEvent (elem, type, func) {
    if (document.addEventListener){
        newAddEvent = function(element, type, func){
            element.addEventListener(type, func);
        }
    } else {
        newAddEvent = function(element, type, func){
            element.attachEvent(type, func);
        }
    }
    newAddEvent(elem, type, func);
}

在這個函數中,第一次調用的時候會進行判斷支持的方法類型,而後就會替換掉原來函數的內容,最後都會執行新的函數。雖然這個是一個簡單的例子,可是能夠把它引伸而且使用到其它複雜的環境中去,這樣就能夠提升運行的效率了。app

面向特徵編程(AOP)

面向特徵編程的全稱是: Aspect-oriented Programming。面向特徵編程本質上就是使用函數執行先後的代碼去擴展當前的函數,而不是使用繼承的方式去擴展。函數

在調試一段代碼的時候,須要在這個代碼被調用的時候寫一些日誌,包括 傳入的參數以及函數調用以後的返回值,而且這樣不會影響到函數的正常執行 ,咱們能夠這樣寫:學習

Bar = {
    foo: function(){ ... }
};

Bar.foo = Bar.foo.debug(function(original, args){
        var _r;
        console.log(args);
        _r = original(args);
        console.log(_r);
        return _r;
});

(注: 此處的參數部分簡略寫了,不要在乎這些細節~) 我在這裏擴展了Function的prototype的方法,將原始函數做爲第一個參數傳入,其實還能夠稍加改變,在新的一個函數上進行這種包裝。 接下來咱們來看看debug的實現:優化

Function.prototype.debug = function(debugger) {
    var _selfMethod = this; // 原始方法的引用
    return function(){
        var args = [];
        for (var i = 0, argsLength = arguments.length; i < argsLength; i++) {
            args.push(arguments[i]);
        }
        return debugger.apply(this, [_selfMethod.bind(this)].concat(args));
    }
};

這段代碼首先保存了原始函數的一個引用,而後將參數傳入debugger並使用apply執行。this


第一次在segmentFault寫blog,也是算對本身的一種鞭策吧,記錄一些所學習的知識,分享一寫學習的心得。

相關文章
相關標籤/搜索