054-手写一个惰性函数
1. 什么是惰性函数
惰性函数是指在运行时,根据条件判断,动态地替换掉函数的实现,从而避免每次调用函数时都执行相同的代码。
2. 为什么要使用惰性函数
在 JavaScript 中,函数的执行环境是全局环境,每次调用函数时,都会执行相同的代码,这会导致一些不必要的性能开销。使用惰性函数可以避免这种情况,通过在函数内部判断条件,动态地替换函数的实现,从而提高性能。
比如写一个获取样式的函数,在 IE 浏览器中,需要使用 currentStyle 而在标准浏览器中,需要使用 getComputedStyle。正常写法是这样的
function getCss(element, attr) {
if ("getComputedStyle" in window) {
return window.getComputedStyle(element)[attr];
}
return element.currentStyle[attr];
}
getCss(document.body, "margin");
getCss(document.body, "padding");
getCss(document.body, "width");
从这个例子中,我们可以看出来,如果需要 3 次获取元素的样式,明显每一次进入函数都需要判断该方法兼容与否,这就造成了不必要的浪费。最好的解决方案——惰性函数思想。 通俗的来说,惰性函数初始化第一次渲染的时候执行,如果第二遍执行还是一样的效果,我们需要用闭包的思想解决这一问题。 改成惰性函数后写法如下:
function getCss(element, attr) {
if ("getComputedStyle" in window) {
getCss = function (element, attr) {
return window.getComputedStyle(element)[attr];
};
} else {
getCss = function (element, attr) {
return element.currentStyle[attr];
};
}
// 为了第一次也能拿到值
return getCss(element, attr);
}
getCss(document.body, "margin");
getCss(document.body, "padding");
getCss(document.body, "width");
在这个函数中,当我们第一次执行 getCss 函数的时候,就已经可以确定 getComputedStyle 兼容与否了,所以在第二次就没必要再判断了,根据第一次判断完返回的结果,直接确定第二次,第三次的函数执行到底用哪个 API,这样以来每次函数执行,都将少了一层判断,一定程度上提高了 js 的运行速度。 那么我们来看,这个惰性体现在哪里呢? 过程:其实,是第一次 getCss 函数执行完创建了全局作用域下的私有执行上下文,而在其里面重新生成了 getCss 函数,将其引用地址重新赋值给全局函数 getCss,导致全局下的 getCss 不能被释放,形成了一个闭包。在以后每次执行时,都执行里面的小函数 getCss。
下面是一个实现示例:
## 示例 2:获取当前浏览器类型
```javascript
function getBrowser() {
if (navigator.userAgent.indexOf("Chrome") > -1) {
getBrowser = function () {
return "Chrome";
};
} else if (navigator.userAgent.indexOf("Firefox") > -1) {
getBrowser = function () {
return "Firefox";
};
} else {
getBrowser = function () {
return "Unknown";
};
}
return getBrowser();
}
```
## 示例 3:事件绑定的惰性函数
```javascript
function addEvent(element, type, handler) {
if (window.addEventListener) {
addEvent = function (element, type, handler) {
element.addEventListener(type, handler, false);
};
} else if (window.attachEvent) {
addEvent = function (element, type, handler) {
element.attachEvent("on" + type, handler);
};
}
return addEvent(element, type, handler);
}
```
## 惰性函数的优点:
1. 避免重复的条件判断,提高代码执行效率
2. 根据环境自动适配最优的执行方案
3. 代码结构清晰,易于维护
## 使用场景:
1. 浏览器环境检测
2. 特性检测