변경 가능한 값을 일급 함수로

function ValueCell(initialValue) {
    var currentValue = initialValue;
    return {
        val: function() {
            return currentValue;
        },
        update: function(f) {
            var oldValue = currentValue;
            var newValue = f(oldValue);
            currentValue = newValue;
        }
    };
}
var shopping_cart = ValueCell({});

shopping_cart.update(function(cart) {
	return add_item(cart, item);
})

shopping_cart.val();

감시자 추가

function ValueCell(initialValue) {
    var currentValue = initialValue;
    var watchers = [];
    return {
        val: function() {
            return currentValue;
        },
        update: function(f) {
            var oldValue = currentValue;
            var newValue = f(oldValue);
            if (oldValue !== newValue) {
                currentValue = newValue;
                forEach(watchers, function(watcher) {
                    watcher(newValue);
                });
            }
        },
        addWatcher: function(f) {
            watchers.push(f);
        }
    };
}
shopping_cart.addWatcher(update_shipping_icons);

다른 셀의 변화를 감지해 따라서 바뀌는 셀

function FormulaCell(upstreamCell, f) {
    var myCell = ValueCell(f(upstreamCell.val()));
    upstreamCell.addWatcher(function(newUpstreamValue) {
        myCell.update(function(currentValue) {
            return f(newUpstreamValue);
        });
    });
    return {
        val: myCell.val,
        addWatcher: myCell.addWatcher
    };
}