Day09 - 闭包应用1 - 制造惰性函数

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


基本概念

惰性函数是函数是编程的一个重要概念。可以有效提高程序的运行效率。

惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。

如何实现计算缓存

假设有一个计算比如计算 平方,非常耗费时间。

需要把平方缓存起来,这样就不需要每次都计算了。

var cache = {}
function square(n) {
if (!cache[n]) {
cache[n] = n * n;
}
return cache[n];
}

使用闭包隐藏全局变量

以上代码虽然可以实现功能,但是最大的问题就是缓存需要定义一个全局变量。其实这个变量是可以隐藏的。

var square = (function () {
var cache = {};
return function(n) {
if (!cache[n]) {
cache[n] = n * n;
}
return cache[n];
}
})();

惰性函数还能做什么

单例模式

单例模式是设计模式之一,它保证了一个类只有一个实例。实现方法一般是先判断实例是否存在,如果存在就直接返回,否则就创建了再返回。单例模式的好处就是避免了重复实例化带来的内存开销。

// 单例模式
function Singleton(){
this.data = 'singleton';
}

Singleton.getInstance = (function () {
var instance;

return function(){
if (instance) {
return instance;
} else {
instance = new Singleton();
return instance;
}
}
})();

var sa = Singleton.getInstance();
var sb = Singleton.getInstance();
console.log(sa === sb); // true
console.log(sa.data); // 'singleton'

单例模式前端最典型的应用场景,全局唯一消息框

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.model {
width: 200px;
height: 200px;
border: 1px solid aqua;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
</style>
</head>

<body>
<div id="loginBtn">点我</div>
<script>
var getSingle = function (fn) {
var result; //缓存实例
return function () {
return result || (result = fn.apply(this, arguments))
}
}
var createLoginLayer = function () {
var oDiv = document.createElement("div");
oDiv.innerHTML = "我是登录浮窗";
oDiv.className = "model";
oDiv.style.display = "none";
document.body.appendChild(oDiv);
return oDiv;
}
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById("loginBtn").onclick = function () {
//动态创建弹窗
//新建一个弹窗实例,内部使用单例模式管理,一直只能有一个.
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "block"
}
</script>
</body>

提高浏览器兼容问题的执行效率

为了解决浏览器之间的行为差异,经常会在代码中包含了大量的 if 语句,以检查浏览器特性,解决不同浏览器的兼容问题。

显然这些if语句我们只希望在一个浏览器中只执行一遍。

function addEvent(type, element, fun) {
if (element.addEventListener) {
element.addEventListener(type, fun, false);
}
else if (element.attachEvent) {
element.attachEvent('on' + type, fun);
}
else {
element['on' + type] = fun;
}
}

最佳的办法就是使用惰性函数将结果缓存起来。

function addEvent(type, element, fun) {
if (element.addEventListener) {
addEvent = function (type, element, fun) {
element.addEventListener(type, fun, false);
}
}
else if (element.attachEvent) {
addEvent = function (type, element, fun) {
element.attachEvent('on' + type, fun);
}
}
else {
addEvent = function (type, element, fun) {
element['on' + type] = fun;
}
}
return addEvent(type, element, fun);
}

第一次执行: 选择合适的api并且执行

第二次执行: 由于addEvent已经被指定为其中的一种

最后我们再看看ajax兼容性的代码

没有惰性

function createXHR(){
var xhr = null;
try {
// Firefox, Opera 8.0+, Safari,IE7+
xhr = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
xhr = null;
}
}
}
return xhr;
}

惰性

function createXHR() {
var xhr = null;
if (typeof XMLHttpRequest != "undefined") {
xhr = new XMLHttpRequest();
createXHR = function () {
return new XMLHttpRequest();
};
} else {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
createXHR = function () {
return new ActiveXObject("Msxml2.XMLHTTP");
};
} catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
createXHR = function () {
return new ActiveXObject("Microsoft.XMLHTTP");
};
} catch (e) {
createXHR = function () {
return null;
};
}
}
}
return xhr;
}

面试攻略

点评

  • 闭闭包处处都有,但是能说出经典应用又是一个难题。说Helloworld和背题没啥区别。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6