通过在JavaScript中将函数转换为对象可以实现什么?

时间:2012-07-18 20:47:19

标签: javascript programming-languages functional-programming

JavaScript的一个独特功能是'函数是对象,可以像任何对象' [1] 一样传递。

当Eich先生开始创作语言时,他为什么决定这样做?与Java等语言中常见的OOP风格相比,它有何优势?他有先例还是当时这是一个完全独特的想法?

2 个答案:

答案 0 :(得分:4)

当然,他并没有发明它,first-class functions自60年代以来一直存在。

它给你的力量是写出所谓的高级函数 - 将其他函数作为参数的函数。这是函数式编程的基石。例如,Array.map是一个将另一个函数作为输入的函数,允许强大的构造。

面向对象的编程是后来开发的,更多地集中在耦合/分离数据和行为上。这通常是以容易推理代码为代价的(在口语和数学意义上)。许多OO语言(Java,C#)现在正在添加函数式编程的这些元素(即lambdas)。

考虑使用Java等语言实现Array.mapArray.reduceArray.filter的复杂性。每次要使用它时,都必须创建一个特殊匿名内部类的实例,只是为了实现算法调用所需的功能。在JavaScript中,函数只是像其他所有东西一样的对象,所以你可以只传入一个,从而产生更加简洁和自然的语法。

答案 1 :(得分:2)

@OrangeDog将它放在鼻子上。我写这个答案只是为了指出你实际上可以实现所有"经典"仅使用函数,数组和递归进行命令式流控制(假设为true == 1且false == 0):

function ifElse(cond, trueFunc, falseFunc) {
    var paths = [falseFunc, trueFunc]
    return paths[cond()]();
}

function whileTrue(cond, action) {
    return ifElse(cond, whileTrue(cond, action), function() {});
}

function forLoop(initial, cond, increment, action) {
    initial();
    return whileTrue(cond, function() {
        var actionValue = action();
        increment();
        return actionValue;
    }
}

function first(array) { // or ``car``
    return array[0];
}

function rest(array) { // or ``cdr``
    return array.slice(1);
}

function each(array, action) {
    action(first(array));
    each(rest(array), action);
}

等等。这是Javascript的Lisp / Scheme根源(它的原型继承模型取自Self,以及来自C / Java的语法)的结果,它可以非常强大,因为您可以轻松定义< em> new 流量控制机制,无需对语言本身进行任何更改,例如:

function categorizer(array, categorizer) {
    var categories = {};
    array.forEach(function(value, index, array) {
        var category = categorizer(value, index, array);
        ifElse(function() {
            return categories[category] instanceof Array ? 1 : 0;
        }, function() {
            categories[category].push(value);
        }, function() {
            categories[category] = [value];
        });
    });
    return categories;
}

categorizer现在可以使用一个函数来定义如何将数组拆分为对象中的一组带标签的数组,可以在别处使用,例如:

categorize(['foo', 'bar', 'baz'], function(value) {
    return value.charAt(0);
});

// Produces the following:
{
    f: ['foo'],
    b: ['bar', 'baz']
}