代码改变世界

JavaScript基础函数的属性:记忆模式(019)

2014-09-17 00:03  Bryran  阅读(190)  评论(0编辑  收藏  举报

函数在Javascript里是有属性的,因为它们是一种特殊对象。事实上,就算是没有明确声明,函数在最初就已经包含了一些固有的属性,比如所有函数都length这个属性,它可以指出函数声明了多少个参数:

function func(a, b, c) {}
console.log(func.length); // 3
 
你 可以随时使用函数的属性。其中一个函数属性的用法是,把函数的返回值保存起来,方便下次执行时再使用,这就是函数的记忆模式。比如,下面的函数myFun 就声明了一个叫cache的属性,可以通过myFun.cache来访问,而cache又是一个对象,通过保存相应的键值对,保存myFun的执行结果:
var myFunc = function (param) {
    if (!myFunc.cache[param]) {
        var result = {};
        // ... expensive operation ...
        myFunc.cache[param] = result;
    }
    return myFunc.cache[param];
};
// cache storage
myFunc.cache = {};

 

上面的例子可以适用于函数使用一个参数的情况,如果函数接受多个参数,则可以先把这些参数变成JSON字符串,再把这个字符串作为Key来保存程序的执行结果:
var myFunc = function () {
    var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
        result;
    if (!myFunc.cache[cachekey]) {
        result = {};
        // ... expensive operation ...
        myFunc.cache[cachekey] = result;
    }
    return myFunc.cache[cachekey];
};
// cache storage
myFunc.cache = {};

 

这种做法有的缺点是,把参数变成JSON字符串后,它有对象“标识”就丢失了,这样,如果有两次执行过程中的参数是不同的对象,但它们的属性相同,那么只会为它们保存一个执行结果。
另一种完成相同功能的实现采用了arguments.callee,这种写法比较通用,不用把每个函数名都写出来。但ECMAScript 5 标准中并不支持arguments.callee。
var myFunc = function (param) {
    var f = arguments.callee,
        result;
    if (!f.cache[param]) {
        result = {};
        // ... expensive operation ...
        f.cache[param] = result;
    }
    return f.cache[param];
};
// cache storage
myFunc.cache = {};

 

参考:

javascript中的memoization(memoizing) 技术介绍