2

既存の関数に機能を追加する方法が欲しかったので、次のようにしました。

Function.prototype.attachFunction = function(toAttach)
{
    var func = this; //This is the original function, which I want to attack toAttach function to.

    //Can I do this without wrapping it in a self-executing function? What's the difference?
    func = (function()
    {
        return function()
        {
            func();
            toAttach();
        }
    })();

    return func; //Return the newly made function, not really important.    
}

これをGoogleChromeコンソールに貼り付けましたが、エラーはありませんが、元の機能はまったく変更されていません(または変更されていないように見えます)。

f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f(); //Prints out just "g".
4

6 に答える 6

1

プロトタイプに設定したattachFunctionメソッドFunctionは、関数を受け入れて新しい関数を返す高階関数またはコンビネーターです。予想通り、その後に作成された関数に継承されます。ただし、呼び出された場合、の状態はまったく変更されずf、を呼び出す新しい関数f、または呼び出し元の関数が生成されるだけです。

したがって、両方のメッセージを表示したい場合console.logは、次のように、返される関数を呼び出す必要があります。

f.attachFunction(function(){console.log("hi")})();
またはもっと簡単に:
f.attachFunction(f)();

関数はオブジェクトですが、の実行コンテキスト(コード)は直接操作できるようなfプロパティではなく、内部属性に保持されていることに注意してください。f

于 2012-07-14T02:39:29.533 に答える
1

attachFunction実行すると、実行する関数とを返しfunc()ますtoAttach。ただし、コードを次のように変更すると、両方の関数が実行されようとします。現在、最後に古いfが呼び出されています。

f = function() {console.log("g");};
f = f.attachFunction(function(){console.log("New function!");});
f(); //Causes an infinite loop since calling func() is the same as calling this()

2つの関数をマージするには、同じ方法でラップする必要がありますが、関数を拡張する必要はありません。

var func1 = function(){
    console.log('g');
};
var func2 = function(){
    console.log('New function!');
};

func1 = (function(f1,f2){
    return function(){            
        f1();
        f2();
    }
}(func1, func2));

func1(); //Writes out both g and New function!​​​​​​​​​​​​​​​​​​​​

func1とfunc2をパラメーターとして渡す理由は、無限ループに入るという同じ問題を防ぐためです。その時点でこれらの関数への参照を維持したいと思います。

その場合、ヘルパー関数は次のようになります。

function combineFunctions(f1, f2){
    return function(){
        f1();
        f2();
    }
}

このように使用されます

var f = function() {console.log("g");};
f = combineFunctions(f,function(){console.log("New function!");});
f();
于 2012-07-14T02:42:36.057 に答える
0

現在、変数を関数であるかのように呼び出そうとしています(toAttach変数であり、その反対側に括弧を付けています)。これを考慮してください: toAttach関数を含むかもしれませんが、それは関数にはなりません(食料品店がリンゴではないように)。代わりに、変数に含まれる関数を呼び出す必要があります。

これを行うにはいくつかの方法がありますが(ここでは1つか2つしか適用されませんが)、[正しい]方法はどれもeval()(人生のレッスン)含まれていません。

このスレッドを考えてみましょう。関数名を文字列として渡してから、

window[toAttach]();

関数を呼び出します。これは少しハッキーで、関数をオブジェクトとして渡すという巧妙さを欠いていますが、機能します。

または(完全にニーズに応じて)、関数をイベントにバインドできます。あなたが非常に卑劣な場合(そしてなぜそうではないのですか?)、あなたは使うことができます

setTimeout(toAttach, 0);

toAttach実際の関数への参照はどこにありますか(ここでも)。

最後に、そして最も良いのは、Function.call()メソッドだと思います。これを使用すると、変数に詰め込まれた関数を呼び出したり、のコンテキストを渡すこともできますthis

toAttach.call([Context]);

関数のコンテキストはどこ[Context]にありますか(つまり、this関数内の場合は何を指しますか。ほとんどの場合、目的のスコープを取得するために空白のままにすることができます)。私はあなたの特定の状況下でそれをテストしたとは言えませんが(したがって、私が最後にそれを含めた理由)、それはあなたが探している結果をあなたに与えるはずだと信じています。

于 2012-07-14T02:01:13.343 に答える
0

Underscore.jsのwrap()関数は、必要なものに非常に近いはずです。

于 2012-07-14T01:55:08.853 に答える
0

これを達成するための私の試みは、完全にプロトタイプにあるかのようにきれいではありませんが、機能します。私よりもおそらく良い方法があります。

var bindings={};

function execBindings(func_name) {
    if (bindings[func_name] != undefined) {
        for (var i=0;i<bindings[func_name].length;i++) {
            bindings[func_name][i]();
        }
    }
}

Function.prototype.bind=function(action){
    if (bindings[this.name] == undefined) {
        bindings[this.name]=[];
    }
    bindings[this.name].push(action);
}

次に、バインディングを使用するには:

function f() {
    alert("foo");
    execBindings("f");
}

f.bind(function(){
    alert("bar");
});

f.bind(function(){
    alert("test");
});

f();

これにより、関数にバインドされた順序で3つのアラートが発生します。

于 2012-07-14T02:28:38.980 に答える
0

私が見つけた2つの問題があります。

問題1。

f = function() {console.log("g");};
f.attachFunction(function(){console.log("New function!");});
f();

それは間違いなく機能しませんattachFunction。元の関数をラップしてラップを返すだけです。元の関数は変更されません。つまり、f関数はまだ残っています。f = function() {console.log("g");}

問題2。

fの結果で再割り当てするとattachFunctionMaximum call stack size exceededが発生します。の定義ではattachFunction

func = (function()
{
    return function()
    {
        func();
        toAttach();
    }
})();

return func; 

func関数は自分自身を再帰的に呼び出します。

アップデート

私はこのアプローチを好みます。

Function.prototype.attachFunction = function(toAttach)
{
    var that = this; 

    func = (function()
    {
        return function()
        {
            that();
            toAttach();
        }
    })();

    return func; //Return the newly made function, not really important.    
}
f = function() {console.log("g");};
f = f.attachFunction(function(){console.log("New function!");});
f();
于 2012-07-14T03:31:41.680 に答える