# 惰性函数
# 定义
我们都使用过缓存,也就是拿 if 来判断,如果存在就直接返回,否则就进行计算。
但是惰性函数,是它的加强版,但是它的使用范围偏小,当我们确定它只有一中特性的时候,我们使用惰性函数,不用判断,也不会更改。
# 第一版
function square(num) {
return Math.sqrt(num)
}
foo(4);
foo(5);
每一次都会进行计算的。
我们来使用缓存我们可以给它缓存起来, 下次访问的时候直接返回就好.
var cache = {};
function square(num) {
if (!cache[num]) {
cache[num] = num * num;
}
return cache[num];
}
# 第二版 (闭包)
上面这种变量直接暴露在了全局下,我们利用闭包。
var square = (function () {
var cache = {};
return function (num) {
if (!cache[num]) {
cache[num] = num * num;
}
return cache[num];
}
})()
square(5); // 25
square(4); // 16
或者我们使用函数(函数对象), 可以将函数当成对象.
function square(num) {
foo.cache = {};
if (!foo.cache[num]) {
cache[num] = num * num;
}
return cache[num];
}
square(5); // 25
square(4); // 16
# 第三版
我们可以看出来,square调用 ,依然要每次都进行 if / else 判断,而真正的惰性函数只会走一次判断。
var square = function (num) {
var cache = {};
cache[num] = num * num;
square = function () {
return cache[num];
}
return square();
}
square(5); // 25
square(4); // 25
利用js弱类型语言的特点,重写变量 square。num 也至此变成了 5.
为什么拿这个例子来讲,是为了让你感觉惰性函数和单纯缓存的特点,如果我们真的在对象下面保存了一个很耗时的对象,我们这么来可以,之后再也不会改变了。但是如果是一个计算的函数,这样将永远变为一个计算值,划不来。
# 应用 (单例模式)
function Singleton() {
this.data = 'singleton';
}
Singleton.getInstance = (function () {
var instance;
return function () {
if (instance) {
return instance;
} else {
instance = new Singleton();
return instance;
}
}
})();
var s1 = Singleton.getInstance();
var s2 = Singleton.getInstance();
s1 === s2; // true;
// 改掉 if
function Singleton() {
this.data = 'singleton';
}
Singleton.getInstance = function () {
var instance;
instance = new Singleton();
Singleton.getInstance = function () {
return instance;
}
return Singleton.getInstance();
}
var s1 = Singleton.getInstance();
var s2 = Singleton.getInstance();
s1 === s2; // true
# DOM 事件
为了兼容现代浏览器和 IE 浏览器,我们需要对浏览器环境进行一次判断。其实,只要我们检测过一次,就能够确定下来了。
function addEvent(type, el, fn) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
} else if (window.attachEvent) {
el.attachEvent('on' + type, fn);
}
}
我们可以这样写
function addEvent(type, el, fn) {
if (window.addEventListener) {
addEvent = function (type, el, fn) {
el.addEventListener(type, fn, false);
}
} else if (window.attachEvent) {
addEvent = function (type, el, fn) {
el.attachEvent('on' + type, fn);
}
}
}
我们也可以使用闭包
var addEvent = (function () {
if (window.addEventListener) {
return function (type, el, fn) {
el.addEventListener(type, fn, false);
}
} else if (window.attachEvent) {
return function (type, el, fn) {
el.attachEvent('on' + type, fn);
}
}
})()
# 总结
如果我们想要缓存结果,并且我们不想要每次都判断,一次就再也不会更改,就可以使用惰性函数。