0

質問のタイトルが誤解を招く場合は、お詫び申し上げます。実際、私は次のPythonコードに相当するjavascriptを探しています。


## python code
def call_with_context(fn, *args):
  ## code to create context, e.g. profiling, db.connect, or drawing context store stack
  fn(*args)
  ## code to close context 

これは、アスペクト指向パラダイムを実装するpythonの「withステートメント」と同様の機能を実装します。

だから私の質問は、そのようなことをするjavascriptの方法は何ですか?Array.prototype.slice(arguments、1)を使用してこれを行うコードを見たことがありますが、これがjavascriptの一般的なパターンなのか、それともjavascriptでサポートされているより良いパターン(クロージャーなど)があるのか​​わかりません。本当にそうしないでください。間違ったキーワードを使用している場合も、サンドイッチよりも適切な名前で問題を参照する方法がわからないため、plsは私を修正します。

EDT 1:そして、ラッパーcall_with_context内からfn(* args)の結果を返す方法を誰かが説明できれば幸いです。ありがとう!

4

5 に答える 5

1

特定のコンテキストでメソッドを呼び出したいようです。

jsでは、通常、次のようにします...

function someFunction( fn, context ) {
   fn.call( context );
}

var Button = {
   isClicked: false
};
someFunction(function () {
   // this === Button
   this.isClicked = true;
}, Button );

これで、thisinside内のキーワードはfn、メソッドに渡されるコンテキストを表しますsomeFunction。この種のパターンは非常に頻繁に行われます。特にコールバックで。

于 2012-07-07T03:32:46.067 に答える
1

これを行うためのより典型的なJSの方法は、関数を装飾することかもしれないと思います。したがって、タイミングを記録したもので関数をラップしたい場合は、次のような関数を作成できます(頭のてっぺんから)。

var createTimer = function(fn) {
    return function() {
        var start = new Date();
        var result = fn.apply(this, arguments);
        console.log("Took " + (new Date() - start) + " ms.");
        return result;
    }
};

var test = function(a, b, c) {
    return a * b + c;
}

test = createTimer(test);

console.log(test(3, 4, 5));

// Took 0 ms.
// 17

重要な点は、次のようなものを呼び出さない可能性があるということです。

runTimerAround(test, 3, 4, 5);

これはJSでも実行できますが、関数を直接上書きするよりも一般的ではないと思います。

于 2012-07-07T04:14:10.893 に答える
0

このようなもの

// javascript code
function call_with_context(fn) {
  // code to create context, e.g. profiling, db.connect, or drawing context store stack
  var r = fn.call(Array.prototype.slice.call( arguments, 1)); // remove first arg - fn 
  //code to close context 
  return r; 
}

だからあなたはこれを行うことができるでしょう:

call_with_context(myfun,1,2,3);

それは電話で終わるでしょう

myfun(1,2,3);
于 2012-07-07T03:47:03.723 に答える
0

これがいくつかの検索後の私の解決策です。それが他の人に役立つことを願っています。


function call_with_context(fn) {
  // some beginning code
  console.log('begin');

  r = fn.apply(null, Array.prototype.slice.call(arguments, 1));

  // some ending code
  console.log('end');

  return r;
}
于 2012-07-07T07:59:13.280 に答える
0

[javascript]すべての投稿/コメントを注意深く読んだ後、OPはとを探していると思います[method-modification]。そして、用語に関するOPの質問にすぐに答えると、JavaScriptで閉じた機能を変更することは、 AOであると主張する実装が少なくともアスペクトアドバイスポイントカットの抽象化とコード再利用レベルを提供しない限り、アスペクト指向プログラミングとは何の関係もありません。

Scott Sauyetがすでにコメント しているように、他のすべては、機能を互いに(手動で)ラップするだけで実行できます。ここでも、私はそれほど遠くまでは行かず、それをfunction-compositionと呼びます。composeその資格を得るには、さまざまな実装やcurryメソッド/パターンがすでに存在するため、少なくともいくつかのツールセットが必要です。

OPが達成しようとしていることについてはbefore、多くの解決策がありafter aroundますが、ほとんどの場合、残念ながらAO(P)wrapに言及しており、多くの場合、コンテキストに注意を払っていないか、これは不可欠であり、OPからも求められています。 。target

私が提供する例では、のプロトタイプ実装を使用していますFunction.around。JavaScriptはすでに標準化された機能を備えているので、、、、、 など の他のメソッド修飾子にも適切な場所で ある と bind確信して い ます。Function.prototypebeforeafteraroundafterThrowingafterFinally

後で次の例をサポートするコードベース:

(function (Function) {
  var
    isFunction = function (type) {
      return (
           (typeof type == "function")
        && (typeof type.call == "function")
        && (typeof type.apply == "function")
      );
    },
    getSanitizedTarget = function (target) {
      return ((target != null) && target) || null;
    }
  ;
  Function.prototype.around = function (handler, target) { // [around]
    target  = getSanitizedTarget(target);

    var proceed = this;
    return (isFunction(handler) && isFunction(proceed) && function () {

      return handler.call(target, proceed, handler, arguments);

    }) || proceed;
  };
}(Function));

サンプルコード、その前後に追加で提供された動作によって特定の閉関数を変更し、そのコンテキストも提供します。

var loggingDelegate = function () { // closed code that can not be changed for any reason.

  this.log.apply(this, arguments);
};


loggingDelegate.call(console, "log", "some", "arguments");


var interceptedLoggingDelegate = loggingDelegate.around(function (proceed, interceptor, args) {

  // everything that needs to be done before proceeding with the intercepted functionality.


  // [this] in this example refers to [console], the second argument of the [around] modifier.

  this.log("proceed:", proceed);         // the original functionality  - here [loggingDelegate].
  this.log("interceptor:", interceptor); // the modifying functionality - [around]s 1st argument.
  this.log("args:", args);               // the arguments that get passed around.


  proceed.apply(this, args);
  // or:
  //return proceed.apply(this, args);
  // or:
  //var result = proceed.apply(this, args);


  // everything that still needs to be done after invoking the intercepted functionality.

  // if necessary:
  //return result;

}, console); // [console] has to be provided as target to the modified [loggingDelegate].


interceptedLoggingDelegate("intercept", "and", "log", "some", "arguments");
于 2014-12-25T17:47:54.613 に答える