JavaScript函数currying对实例方法不起作用

时间:2013-03-24 20:14:57

标签: javascript function partial-application

我正在通过在线阅读和编写一些简单的代码来学习JavaScript中的函数。我在网上文章中得到了以下示例

    function toArray(obj) {
        return Array.prototype.slice.call(obj);
    }

    Function.prototype.curry = function() {
        if (arguments.length<1) {
            return this; //nothing to curry with - return function
        }
        var __method = this;
        var args = toArray(arguments);
        return function() {
            return __method.apply(this, args.concat(toArray(arguments)));
        }
    }

    var add = function(a,b) {
        return a + b;
    }

    var addTen = add.curry(10); //create function that returns 10 + argument
    alert(addTen(20)); //alerts 30 correctly

然后我尝试在实例化函数的方法上尝试它。所以我试着跟随。但它给了我错误“无法获得未定义或空引用的属性'原型'在第二行。我知道这个错误与currying无关,但我搞砸了JS函数概念的一些基础知识。所以我哪里出错了。

    function Person()
    {
        this.age = 15;
    }

    Person.ageAfter = function (years) {
        return this.age + years;
    }

    var personObj = new Person();
    var ageAfterFiveYears = personObj.ageAfter.prototype.curry(5);  //**Error**
    alert(ageAfterFiveYears());

3 个答案:

答案 0 :(得分:4)

您不应在通话中包含原型:

var ageAfterFiveYears = personObj.ageAfter.curry(5);

“ageAfter”属性具有其值的功能,因此该功能可以像第一个示例中的功能一样访问“咖喱”功能。

当你在原型上调用它时,你函数中this的值将是原型对象,而不是“ageAfter”函数。

另外,正如评论所指出的,你需要在原型上加上“ageAfter”:

Person.prototype.ageAfter = function(years) { ... }

编辑 - Alnitak指出的绑定问题也很重要。 (当我说“重要”时,我的意思是“使你的代码有效”。)

答案 1 :(得分:3)

您有两个问题:

  1. ageAfter函数不是实例方法 - 您已将其添加到“类”(即它有点像静态方法)。它应该添加到原型中。

  2. 当您对该函数进行操作时会丢失对象的上下文,因此您需要重新绑定上下文

  3. e.g:

    var ageAfterFiveYears = Person.prototype.ageAfter.curry(5).bind(personObj);
    

    为您提供在当前实例上工作的功能,或者更好,正如@Pointy在评论中建议的那样,您应该将curried函数重新放回原型:

    Person.prototype.ageAfterFiveYears = Person.prototype.ageAfter.curry(5);
    

    然后将.ageAfterFiveYears方法添加到每个 Person对象。

答案 2 :(得分:1)

Curry不适用于您的用例。您需要绑定上下文,以便this是您的personObj。

function Person() {
    this.age = 15;
}

Person.prototype.ageAfter = function (years) {
    return this.age + years;
}

var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.bind(personObj, 5);
alert(ageAfterFiveYears());