3

我正在通过在线阅读和编写一些简单的代码来学习 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

然后我尝试了一个实例化函数的方法。所以我试着跟随。但它在倒数第二行给了我错误“无法获取未定义或空引用的属性'原型'”。我知道这个错误与柯里化无关,但我搞砸了 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());
4

3 回答 3

4

您不应该在调用中包含原型:

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

“ageAfter”属性的值有一个函数,因此该函数可以访问您的“curry”函数,就像第一个示例中的函数一样。

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

同样作为评论指出,您需要将“ageAfter”放在原型上:

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

编辑——Alnitak 指出的绑定问题也很重要。(当我说“重要”时,我的意思是“使您的代码工作所必需的”。)

于 2013-03-24T20:19:30.770 回答
3

你有两个问题:

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

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

例如:

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

为您提供一个适用于当前实例的函数,或者更好的是,正如@Pointy 在评论中所建议的那样,您应该将 curried 函数放回原型中:

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

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

于 2013-03-24T20:22:41.553 回答
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());
于 2013-03-24T20:23:02.847 回答