関数を呼び出す5つの方法

JavaScriptコードを扱う必要があります。JavaScriptエラーは、関数がJavaScriptでどのように機能するかについての誤解が原因です(ちなみに、このようなコードの大部分は自分で作成しました)。 JavaScriptはマルチパラダイム言語であり、機能的なプログラミングメカニズムを備えています。 これらの可能性を探る時が来ました。 この記事では、JavaScriptで関数を呼び出す5つの方法について説明します。

JavaScriptを学習する最初の段階では、初心者は通常、JavaScriptの機能がC#の場合とほぼ同じように機能すると考えています。 ただし、JavaScriptで関数を呼び出すためのメカニズムには多くの重要な違いがあり、それらを無視するとエラーを見つけやすくなります。

3つの要素の配列を返す単純な関数を書きましょう-これの現在の値と関数に渡される2つの引数。
 function makeArray(arg1, arg2){ return [ this, arg1, arg2 ]; } 

最も一般的な方法:グローバルコール


多くの場合、初心者は上記の例に示すように関数を宣言します。 この関数の呼び出しは簡単です。
 makeArray('one', 'two'); // => [ window, 'one', 'two' ] 

ちょっと待って windowオブジェクトはどこから来たのですか? なぜthiswindowと等しいのですか?

JavaScriptでは、スクリプトがブラウザで実行されようと他の環境で実行されようと、 グローバルオブジェクトは常に定義されます。 何かに「付加」されていない(つまり、オブジェクト宣言の外側にある)スクリプト内のコードは、実際にはグローバルオブジェクトのコンテキスト内にあります。 この場合、 makeArrayはそれ自体が「歩く」関数ではありません。 実際、 makeArrayはグローバルオブジェクト(ブラウザでのコード実行の場合) windowメソッドです。 これは簡単に証明できます:
 alert( typeof window.methodThatDoesntExist ); // => undefined alert( typeof window.makeArray ); // => function 

つまり、 makeArray('one', 'two');への呼び出しmakeArray('one', 'two'); window.makeArray('one', 'two');を呼び出すのとwindow.makeArray('one', 'two');

この関数呼び出し方法が最も一般的であるという事実に悲しんでいます。なぜなら、それはグローバル関数の存在を暗示しているからです。 そして、私たちは皆、グローバル関数とグローバル変数がプログラミングの最高のトーンではないことを知っています。 これは特にJavaScriptに当てはまります。 グローバルな定義は避けてください。後悔することはありません。

関数を呼び出すためのルール1。オブジェクトを指定せずに関数を直接呼び出す場合(たとえば、 myFunction() )、この値はグローバルオブジェクト(コードがブラウザーで実行される場合はwindow )になります。

メソッド呼び出し


単純なオブジェクトを作成し、 makeArrayをメソッドにしましょう。 リテラル表記を使用してオブジェクトを宣言し、メソッドを呼び出します。
 //   var arrayMaker = { someProperty: '- ', make: makeArray }; //   make() arrayMaker.make('one', 'two'); // => [ arrayMaker, 'one', 'two' ] //  ,    arrayMaker['make']('one', 'two'); // => [ arrayMaker, 'one', 'two' ] 

違いがわかりますか? この場合、 this値はオブジェクト自体です。 関数宣言が変更されていないため、前の例のようにwindowを使用しないのはなぜですか? 完全な秘密は、関数がJavaScriptで渡される方法です。 Functionは、実際にはオブジェクトであるJavaScriptの標準タイプであり、他のオブジェクトと同様に、関数を渡してコピーできます。 この場合、引数リストと本文を含む関数全体をコピーし、結果のオブジェクトをarrayMakerオブジェクトのmakeプロパティに割り当てました。 これはそのような宣言と同等です:
 var arrayMaker = { someProperty: '- '; make: function (arg1, arg2) { return [ this, arg1, arg2]; } }; 

関数呼び出し規則#2:メソッド呼び出し構文を使用して呼び出される関数、たとえばobj.myFunction()またはobj['myFunction']()では、値はobjます。

この単純で一般的な原則を理解しないと、多くの場合、イベント処理でエラーが発生します。
 <input type="button" value="Button 1" id="btn1" /> <input type="button" value="Button 2" id="btn2" /> <input type="button" value="Button 3" id="btn3" onclick="buttonClicked();" /> <script type="text/javascript"> function buttonClicked(){ var text = (this === window) ? 'window' : this.id; alert( text ); } var button1 = document.getElementById('btn1'); var button2 = document.getElementById('btn2'); button1.onclick = buttonClicked; button2.onclick = function(){ buttonClicked(); }; </script> 

最初のボタンをクリックすると、メッセージ「btn1」が表示されますこの場合、関数をメソッドとして呼び出し、関数内でこのメソッドが属するオブジェクトの値を取得するためです。 2番目のボタンをクリックすると、 「window」が表示されます。この場合、 buttonClicked直接呼び出すためです(つまり、 obj.buttonClicked()ます)。 3番目のボタンの場合のように、要素タグでイベントハンドラーを割り当てると、同じことが起こります。 3番目のボタンをクリックすると、2番目のボタンと同じメッセージが表示されます。

jQueryのようなライブラリを使用する場合、考える必要はありません。 jQueryは、イベントハンドラーでthis値を書き換えて、 this値がイベントを発生させた要素になるように注意します。
 //  jQuery $('#btn1').click( function() { alert( this.id ); // jQuery   ,  'this'   }); 

jQueryはthis値をどのように変更thisますか? 以下をお読みください。

さらに2つの方法: apply()およびcall()


関数を使用する頻度が高くなるほど、関数を渡して異なるコンテキストで呼び出す必要が頻繁に発生するのは論理的です。 多くの場合、 thisの値をオーバーライドする必要があります。 覚えているなら、JavaScriptの関数はオブジェクトです。 実際には、これは、関数に事前定義されたメソッドがあることを意味します。 apply()call()はそのうちの2つです。 これらの値をオーバーライドできます:
 var car = { year: 2008, model: 'Dodge Bailout' }; makeArray.apply( car, [ 'one', 'two' ] ); // => [ car, 'one', 'two' ] makeArray.call( car, 'one', 'two' ); // => [ car, 'one', 'two' ] 

これら2つの方法は非常に似ています。 最初のパラメーターはthisオーバーライドします。 これらの違いは次の引数にありますFunction.apply()Function.apply()に渡される値の配列を受け取り、 Function.call()は引数を個別に受け取ります。 実際には、私の意見では、 apply()apply()方が便利です。

関数を呼び出すためのルールNo. 3:関数を別のオブジェクトにコピーせずにthis値をオーバーライドする場合は、 myFunction.apply( obj )またはmyFunction.call( obj )使用できます。

コンストラクター


JavaScriptでネイティブ型を宣言することは避けますが、JavaScriptにはクラスがなく、カスタム型にはコンストラクターが必要であることを思い出す必要があると思います。 さらに、コンストラクター関数のプロパティであるprototype使用してユーザー定義メソッドを宣言することをお勧めします。 タイプを作成しましょう:
 //   function ArrayMaker(arg1, arg2) { this.someProperty = ''; this.theArray = [ this, arg1, arg2 ]; } //   ArrayMaker.prototype = { someMethod: function () { alert(' someMethod'); }, getArray: function () { return this.theArray; } }; var am = new ArrayMaker( 'one', 'two' ); var other = new ArrayMaker( 'first', 'second' ); am.getArray(); // => [ am, 'one', 'two' ] 

この例で重要なのは、関数を呼び出す前にnew演算子が存在することです。 彼のためではなかった場合、それはグローバルコールになり、コンストラクターで作成されたプロパティはグローバルオブジェクトを参照します。 必要ありません。 さらに、コンストラクターは通常、明示的に値を返しません。 new演算子がないと、コンストラクターはundefined返し、それを使用してthis返します。 良いスタイルは、大文字のデザイナーの名前です。 これにより、 newオペレーターの必要性を思い出すことができます。

そうでない場合、コンストラクター内のコードは、別の言語で記述するコードのように見える可能性が高くなります。 この場合の値は、作成している新しいオブジェクトです。

関数を呼び出すためのルールNo. 4: new演算子で関数を呼び出すとき、 this値はJavaScriptランタイムによって作成された新しいオブジェクトになります。 この関数がオブジェクトを明示的に返さない場合、これは暗黙的に返されます。

おわりに


関数呼び出しのさまざまな方法の違いを理解することで、JavaScriptコードを改善できることを願っています。 thisの値に関連するエラーをキャッチするのは簡単ではない場合があります。そのため、エラーの発生を事前に防ぐのが理にかなっています。

Source: https://habr.com/ru/post/J119841/


All Articles