标签:
这是一篇[javascript the good parts]的读书笔记。
我们知道可以利用javascript 的prototype 特性为原始类型编写拓展模块。利用如下方法:
Object.prototype.method = function(name, func) { Object.prototype[name] = func }
为javascript 里的所有对象添加一个便捷的扩展方法method. 这个便捷方法省去了我们每次都手工输入Object.prototype.xxxx
现在我们要为string 类型添加一个拓展方法,叫做deentityify,作用是把形如 < 或者 &qout; 这样的字符串替换成他原来的样子。
很自然的,我们需要一个存着替换规则的表:
var entity = { qout: ‘"‘, lt: ‘<‘, gt: ‘>‘ }
但是现在的问题是,这个表应该让他存在哪呢?
方案1.存在全局变量里。
方案2.就存在deentityify 这个函数里。
方案1不可行?,因为全局变量是邪恶的?? 我们应该尽量避免使用全局变量。
那就试试方案2:
String.method(‘deentityify‘, function(){ var entity = { quot: ‘"‘, lt: ‘<‘, gt: ‘>‘ } return this.replace(/&[^&;]+);/g, function(a, b) { var r = entity[b]; return typeof r === ‘string‘ ? r : a; }) }) var s = "<">" s.deentityify() //<">
结果是正确的,但是有个问题,每次调用deentityify 的时候,entity 都被求值一次,这显然会增加开销。
看来方案2也不是最理想的,有没有什么规避的方法呢?设想,如果让entity 只求值一次,然后把他的结果保存下来,以后每次调用deentityify 的时候直接使用entity的结果,而不是每次调用都去把他再求值一次。这可以做到吗?
当然可以,答案就是使用闭包:
String.method(‘deentityify‘, function(){ var entity = { quot: ‘"‘, lt: ‘<‘, gt: ‘>‘ } return function () { return this.replace(/&[^&;]+);/g, function(a, b) { var r = entity[b]; return typeof r === ‘string‘ ? r : a; }) } }())
相比方案2直接返回结果,闭包的方案是返回一个函数,然后立即对他求值,求值的结果作为deentityify 的值。
感觉有点绕,但是这样的一个好处是,entity 只在String.method() 这里被求值,以后,每次用deentityify 的时候,我们都只是直接使用entity 的值,而不用每次都求值了。这就是闭包的威力。
标签:
原文地址:http://www.cnblogs.com/agentgamer/p/4330258.html