JavaScript: The Good Parts のメモ

JavaScript: The Good Parts より、コード断片のメモ。

p.39 Closure

以下のような HTML において、a ~ b をクリックしたときに、0 ~ 3 を出力したい。

<ol>
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
</ol>

何も考えないで書くとこうなる。nodes には li のコレクションが渡っている。

var addHanlders = function(nodes) {
for (var i = 0; i < nodes.length; i++) {
nodes[i].onclick = function() {
console.log(i);
};
}
};

どれをクリックしても 4 が表示される。

クロージャを使うと正しく動作する。

var addHanlders = function(nodes) {
for (var i = 0; i < nodes.length; i++) {
nodes[i].onclick = function(i) {
return function() {
console.log(i);
}
}(i);
}
};

p.41 Curry

カリー化について。

Function.prototype.curry = function() {
var slice = Array.prototype.slice;
var args = slice.apply(arguments);
var scope = this;
return function() {
return scope.apply(null, args.concat(slice.apply(arguments)));
};
};

以下の単純な関数をカリー化してみる。

function add(a, b) {
return a + b;
}
var add1 = add.curry(1);
console.log(add1(6)); //7

p.44 Memoization

メモ化について。理解できていない。

以下は、フィボナッチ数列を出力する関数。

var fibonacci = function(n) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};

項数を 10 で実行すると、442 回も実行されて無駄がある。そこでメモ化。

var fibonacci = function() {
var memo = [0, 1];
var fib = function(n) {
times++;
var result = memo[n];
if (typeof result !== "number") {
result = fib(n - 1) + fib(n - 2);
memo[n] = result;
}
return result;
};
return fib;
}();

呼び出しが 29 回に減った。

memoizer として共通化するとこうなる。

var memoizer = function(memo, fundamental) {
var shell = function(n) {
var result = memo[n];
if (typeof result !== "number") {
result = fundamental(shell, n);
memo[n] = result;
}
return result;
};
return shell;
};
var fibonacci = memoizer([0, 1], function(shell, n) {
return shell(n - 1) + shell(n - 2);
});