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

次に、インスタンス化された関数のメソッドで試してみました。だから私はフォローしてみました。しかし、最後から2行目に「未定義またはnull参照のプロパティ「プロトタイプ」を取得できません」というエラーが表示されました。このエラーはカリー化とは何の関係もないことは知っていますが、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

2つの問題があります。

  1. このageAfter関数はインスタンスメソッドではありません。「クラス」に追加しました(つまり、静的メソッドのようなものです)。プロトタイプに追加する必要があります。

  2. 関数をカレーすると、オブジェクトのコンテキストが失われるため、コンテキストを再バインドする必要があります

例えば:

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

@Pointyがコメントで示唆しているように、現在のインスタンスでのみ機能する関数を提供します。さらに、カリー化された関数をプロトタイプに戻す必要があります。

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

次に、すべてのオブジェクトに.ageAfterFiveYearsメソッドを追加します。 Person

于 2013-03-24T20:22:41.553 に答える
1

カレーはあなたのユースケースでは機能しません。コンテキストをバインドする必要があるので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 に答える