日期:2014-05-16  浏览次数:20304 次

JavaScript学习笔记(十七) 方法的属性

方法的属性(Function Properties)

函数是对象,所以它们可以有属性。事实上,它们有很多可以使用的属性;
比如:每个函数,无论你用什么样的语法形式创建的,都会自动得到一个 length 的属性,包含了函数期待的参数的个数;
function func(a, b, c) {}
console.log(func.length); // 3
你可以在任何时候给你的函数添加自定义的属性
一种函数属性的用法就是缓存函数的结果(the return value),当下一次调用函数时,它不需要再做重复的计算(可能是非常繁重的),缓存函数的结果也被称为是memoization

在下面这个例子,函数myFunc创建了一个cache属性,可以通过myFunc.cache访问,cache属性是一个对象(哈希表),传入函数的参数param会被当做key并且计算结果会被当做value;
var myFunc = function (param) {
if (!myFunc.cache[param]) {
var result = {};
// ... expensive operation ...
myFunc.cache[param] = result;
}
return myFunc.cache[param];
};
// cache storage
myFunc.cache = {};
上面这段代码假设函数只接收一个参数param并且它是基本数据类型(好比string),如果你有更多的参数和更复杂的参数,一个通用的处理办法就是去序列化(serialize)这些参数;
比如:你可以序列化参数为JSON字符串并且可以将这个字符串作为cache对象的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 = {};
在序列化的时候要小心,对象的标识(identify)会丢失,如果你有两个不同的对象碰巧拥有相同的属性,它们会共享相同的缓存;

另一种方法去写前面的函数,用arguments.callee去引用函数而不是硬编码函数的名称。
虽然在现在是可以的,但要小心arguments.callee在ECMAScript的严格模式(strict mode)中是不被允许的
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 = {};