前端面试题(初探函数式编程、对象变量缓存)

<!DOCTYPE html>
<html>
<head>
<title>Quiz</title>
<meta charset="UTF-8">
</head>

<body onload="load();" style="text-align:center;font-size:50px;">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>

<script>
function factorial(i) {
//some code
}

function load() {
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis; i++) {
lis.onclick = function () {
factorial(i);
}
}
}

</script>
</body>
</html>

需求:有一个列表,点击第i个li,弹出i的阶乘。

问题一:代码中有什么错误?哪里可以优化?
答:
错误:
1.i < lis应该是i < lis.length;
2.lis.onlick 应该是lis[i].onclick;
3.因为引入了闭包,onclick中直接调用factorial(i),弹出的都会是同样的结果,都会是lis.length的阶乘。可以通过再引入一个闭包解决;
lis.onclick = (function (i) {
return function () {
factorial(i);
}
})(i);
4.这种事件绑定方式造成了循环引用,在旧版本IE中会出现内存泄露,解决方法同3。

优化:
1.循环优化:储存length,++i,jquery循环,达夫机器;
2.事件绑定用事件监听方式,或用事件委托替代事件绑定。(此处可以继续问事件监听的兼容性和事件委托的原理)

问题二:实现阶乘函数。
一般答案:
function factorial(i) {
return i == 0 ? 1 : i * factorial(i - 1);
}

懒加载闭包实现:
function factorial(i) {
var cache = {};
factorial = function (i) {
console.log('count');
return cache[i] ? cache[i] : (cache[i] = i == 0 ? 1 : i * factorial(i - 1));
}
return factorial(i);
}

函数式编程实现:
function memorize(f) {
var cache = {};
return function (i) {
return cache[i] ? cache[i] : (cache[i] = f.call(null, i));
}
}

var factorial = memorize(function (i) {
console.log('conut');
return i == 0 ? 1 : i * factorial(i - 1);
});

posted @ 2015-12-28 12:06  haigelang  阅读(145)  评论(0编辑  收藏  举报