web-dev-qa-db-ja.com

Javascriptには、これの値を変更しない.applyに相当するものがありますか?

簡単そうですが、引数の配列を使用して関数を呼び出したいと思います。確かに、私はfunc.apply(this, ['some', 'arguments']);と言うことができますが、それはthis内のfuncの値を変更します。それを変更せずにこれを行う方法はありますか?

44
JussiR

ES6では、次のように書くこともできます。

func(...someArray)

ここで、thisWindow内でfuncになりますが、これは役に立ちません。しかし、あなたが書く場合:

obj.func(...someArray)

this内のfuncobjになります。

これは私が5年前に探していた機能かもしれませんが、それは5年前だったので、誰が覚えていますか:)

11
JussiR

JavaScriptでのthisの動作方法のため、はできません。読む:

ECMAScript仕様の "Entering An Execution Context" セクションを参照してください。関数を呼び出すと、thisの値は、残りの値(と呼ばれます)によって決まります。アクティベーションオブジェクト)。 steveという関数を作成し、彼をオブジェクトに入れましょう。

_function steve(){}
var obj = { method: steve };
_

…steveをobj.method()と呼ぶと、thisがアクティベーションオブジェクトであったため、彼のobjobjになります。

トリッキーなケースは、nothingが関数呼び出しの左側にある場合です。

_steve(); // Who am I ?!
_

関数呼び出しの左側にはnothingがあります—事実上null —なので、thisの値はデフォルト値に設定されます。グローバルオブジェクト(Webブラウザではwindow、Node.jsではglobalなど)。

つまり、実際には、関数を呼び出すたびに関数のthisを設定していることになります。

P.S. steve.apply(null, [])を呼び出すことは、steve()を呼び出すことと同じです。

29
s4y

thisの値は、関数を呼び出すときに「通常」(callまたはapplyなし)と呼ばれる方法に応じて、謎ではありません。

func(); // `this` is the global object, or undefined in ES5 strict mode
obj.func(); // `this` is `obj`

したがって、thisの値を「変更」しないようにするには、「通常」と呼ぶ方法に応じて、正しい値をapplyに渡すだけです。

func.apply(undefined, []); // global object, or undefined in ES5 strict mode
obj.func.apply(obj, []);
3
David Tang

関数を単独で呼び出す場合は、nullを渡します。

func.apply(null, ['some', 'arguments']);

オブジェクトのメソッドである関数を呼び出す場合は、そのオブジェクトを渡します。

var arr = [];
arr.Push.apply(arr, ['some', 'arguments']);

どのように this が機能するかを一致させるために。

2
Thai

あなたが望むものはあまり意味がありません。

Ecmascript標準では、thisは次のように定義されています。

11.1.1 thisキーワードthisキーワードは、現在の実行コンテキストのThisBindingの値に評価されます。

関数実行コンテキストのthisBinding解決は、次のように指定されます。

10.4.3関数コードの入力制御が関数オブジェクトF、thisArgを提供する呼び出し元、およびargumentsListを提供する呼び出し元に含まれる関数コードの実行コンテキストに入ると、次の手順が実行されます。

  1. 関数コードが厳密なコードである場合は、ThisBindingをthisArgに設定します。
  2. それ以外の場合、thisArgがnullまたは未定義の場合は、ThisBindingをグローバルオブジェクトに設定します。
  3. それ以外の場合、Type(thisArg)がObjectでない場合は、ThisBindingをToObject(thisArg)に設定します。
  4. それ以外の場合は、ThisBindingをthisArgに設定します。
  5. LocalEnvを、Fの[[Scope]]内部プロパティの値を引数として渡してNewDeclarativeEnvironmentを呼び出した結果とします。
  6. LexicalEnvironmentをlocalEnvに設定します。
  7. VariableEnvironmentをlocalEnvに設定します。
  8. コードをFの[[コード]]内部プロパティの値とします。
  9. 10.5で説明されているように、関数コードコードとargumentListを使用して、宣言バインディングのインスタンス化を実行します。

つまり、指定するか、グローバルオブジェクトに自動的に設定されます。親スコープからこのバインディングを継承することは決してないため、親スコープのthisBindiongをその子に与える唯一の方法は次のいずれかです。

  1. var self = thisのような親スコープのローカル変数に保存します
  2. 質問で指定したコードのように、call/applyで挿入します。
0