JavaScript で次のようなものをよく見かけます。
$("#sendButton").click(function() {
sendForm();
}
sendForm()
への呼び出しを関数内にラップする必要があるのはなぜですか? このようにすると、読みやすくなり、入力が少なくなると思います。
$("#sendButton").click(sendForm);
各アプローチの利点/欠点は何ですか? ありがとう!
JavaScript で次のようなものをよく見かけます。
$("#sendButton").click(function() {
sendForm();
}
sendForm()
への呼び出しを関数内にラップする必要があるのはなぜですか? このようにすると、読みやすくなり、入力が少なくなると思います。
$("#sendButton").click(sendForm);
各アプローチの利点/欠点は何ですか? ありがとう!
通常、後者よりも前者を使用したい場合が 2 つあります。
関数を呼び出す前に、引数に対して後処理を行う必要がある場合。
オブジェクトのメソッドを呼び出す場合、2 番目の形式を使用するとスコープ (この参照) が異なります
例えば:
MyClass = function(){
this.baz = 1;
};
MyClass.prototype.handle = function(){
console.log(this.baz);
};
var o = new MyClass();
$('#foo').click(o.handle);
$('#foo').click(function(){
o.handle();
});
コンソール出力:
undefined
1
答えが多すぎるかもしれませんが、両者の違いは の値this
、つまりスコープが に入るということsendForm
です。(引数も異なります。)説明させてください。
JavaScript 仕様によると、次のようsendForm();
に関数を呼び出すと、コンテキスト オブジェクトなしで関数が呼び出されます。これは与えられた JavaScript です。
ただし、次のように関数を引数として渡す場合は$(...).click(sendForm)
、後で呼び出すために関数への参照を渡すだけです。その関数はまだ呼び出していませんが、オブジェクト参照のように渡しているだけです。がそれに続く場合にのみ、関数を呼び出します (後で説明すると()
は例外です)。いずれにせよ、誰かが最終的にこの関数を呼び出す場合、その誰かは関数を呼び出すスコープを選択できます。call
apply
私たちの場合、その誰かが jQuery です。関数を に渡す$(...).click()
と、jQuery は後で関数を呼び出し、スコープ (this) をクリック イベントの HTML 要素ターゲットに設定します。試すことができ$(...).click(function() { alert(this); });
ます: は、HTML 要素を表す文字列を取得します。
したがって、jQuery に という匿名関数への参照を与えるとsendForm()
、jQuery はその関数を呼び出すときにスコープを設定し、その関数はsendForm
スコープなしで呼び出します。本質的に、それはをクリアしthis
ます。試してみてください: $(...).click(function() { (function() { alert(this); })(); });
. ここでは、無名関数を呼び出す無名関数があります。() が関数に適用されるように、内側の無名関数を括弧で囲む必要があります。
代わりに、名前付きの function への参照を jQuery に与えるとsendForm
、jQuery はこの関数を直接呼び出して、常に与えると約束されているスコープを与えます。
したがって、質問に対する答えはより明白になります。this
で作業を開始するときにクリックの要素ターゲットを指す必要がある場合はsendForm
、 を使用して.click(sendForm)
ください。それ以外の場合は、どちらも同様に機能します。おそらく必要ないのでthis
、無名関数はスキップしてください。
好奇心旺盛な人のために、スコープは JavaScript 標準を使用するか、apply
またはcall
(この2 つの違いについてはこちらを参照してください) を使用して強制できます。スコープは、 のようにドット演算子を使用するときにも割り当てられます。これは、JavaScript に を指すobj.func
関数を呼び出すように要求します。(したがって、理論的には、次のようなことを行うことで、関数を呼び出すときに強制的にスコープにすることができます:しかし、これは apply.this
obj
obj
obj.foo = (reference to function); obj.foo(); delete obj.foo;
スコープを指定してクリック ハンドラを呼び出すために jQuery によって使用されるFunctionapply
は、関数呼び出しで引数を強制することもできます。実際、jQuery はそのクリック ハンドラに引数を渡します。したがって、2 つのケースには別の違いがありsendForm
ます。無名関数から呼び出してパラメーターを渡さない場合、スコープだけでなく引数も失われます。
ここでは、複数の関数をインラインで呼び出すことができる匿名のイベントハンドラーを定義しています。汚くてデバッグするのは難しいですが、人々は怠惰でできるのでそれを行います。
また、2番目の例(イベントハンドラーの定義方法)のように機能します。
$("#sendButton").click(sendForm)
イベントハンドラーをインラインで定義することで得られるものは、イベントデータを複数の関数に渡しthis
、イベントオブジェクトにスコープを設定する機能です。
$("#sendButton").click(function(event) {
sendForm();
doSomethingElse(event);
andAnotherThing(event);
// say #sendButton is an image or has some data attributes
var myButtonSrc = $(this).attr("src");
var myData = $(this).data("someData");
});
を呼び出すだけsendForm
の場合、最終的には、含めた2つの例の間に大きな違いはありません。
$("#sendButton").click(function(event) {
if(event.someProperty) { /* ... */ }
else { sendForm({data: event.target, important: 'yes'}); }
}
ただし、上記の場合、からコールバックに渡される引数を処理できますがclick()
、sendForm関数がこれを処理するためにすでに装備されている場合、それが本当にすべてである場合、コールバック引数としてsendFormを配置しない理由はありません。やっている。
function sendForm(event) {
// Do something meaningful here.
}
$("#sendButton").click(sendForm);
プログラム内のロジックのさまざまなレイヤーを処理するのはあなた次第であることに注意してください。特定の汎用機能を関数にカプセル化してから、それ自体を呼び出す前にイベント/コールバック処理の暫定的なビジネスを処理するこれらの種類の関数に渡すsendForm
関数がある場合があります。sendFormCallback
sendForm
コールバックの多い環境で作業している場合は、コールバックトリガー自体から重要な機能を分離して、コールバックの地獄を回避し、ソースコードの保守性と可読性を促進することをお勧めします。
スコープをロックするだけです。sendForm()
現在のスコープを閉じる匿名関数でそれをラップすると。つまり、 はthis
一緒に保持されます。渡すだけの場合sendForm
、へthis
の呼び出しは呼び出しスコープから行われます。
これは、javascript のスコープについて学習し、規則について質問するのに適した質問です。
いいえ、その2番目の例は完全に有効です。
jQueryの例の99.9%は最初の表記を使用していますが、これは基本的なJavaScript構文を忘れる必要があるという意味ではありません。