<!DOCTYPE html>
<html><head><title>Quiz</title><meta charset="UTF-8"></head><body οnlοad="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);});