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,也是算对本身的一种鞭策吧,记录一些所学习的知识,分享一写学习的心得。

相关文章
相关标签/搜索