序文
call()、apply()、およびbind()メソッドを介して、これらのオブジェクトから継承することなく他のオブジェクトからメソッドを簡単に借りることができます。
JavaScriptの借入方法
JavaScriptでは、他のオブジェクトの関数または方法を再利用することがあり、必ずしもオブジェクト自体またはプロトタイプで定義されるわけではありません。 call()、apply()、およびbind()メソッドを介して、他のオブジェクトを継承せずに他のオブジェクトから簡単に借りることができます。これは、プロのJavaScript開発者が使用する一般的な方法です。
プロトタイプメソッド
JavaScriptでは、文字列、数値、ブール波などの不変のプリミティブデータ型を除き、ほとんどすべてのデータはオブジェクトです。配列は、順序付きシーケンスを通過および変換するのに適したオブジェクトです。そのプロトタイプには、スライス、結合、プッシュ、ポップなどの使いやすい方法があります。
一般的な例は、オブジェクトと配列の両方がリストタイプのデータ構造である場合、オブジェクトは配列からメソッドを「借りる」ことができることです。借りる最も一般的な方法は、 Array.prototype.sliceです。
function myfunc(){//エラー、引数はオブジェクトのような配列であり、実際の配列arguments.sort(); // "借り入れ"配列メソッドは、そのプロトタイプからスライスします。これは、オブジェクト(key:value)のような配列を取得し、実際の配列var args = array.prototype.slice.call(arguments)を返します。 // argsは実際の配列になるので、array args.sort()からsort()メソッドを使用できます。 } myfunc( 'bananas'、 'cherries'、 'apples');貸付方法は、呼び出しと適用の方法により、異なるコンテキストで呼び出し関数が機能するため、機能します。これは、他のオブジェクトを継承することなく既存の関数を再利用する良い方法でもあります。実際、アレイは、結合やフィルターなど、プロトタイプの多くの一般的な方法を定義します。
// take a string "abc" and produces "a|b|cArray.prototype.join.call('abc', '|'); // take a string and removes all non vowelsArray.prototype.filter.call('abcdefghijk', function(val) { return ['a', 'e', 'i', 'o', 'u'].indexOf(val) !== -1;})。join( '');オブジェクトだけでなく、アレイメソッドだけでなく、文字列も借りることができることがわかります。ただし、ジェネリックメソッドはプロトタイプで定義されているため、メソッドを借りたいたびにString.prototypeまたはArray.prototypeを使用する必要があります。このように書くことは非常に冗長であり、すぐに迷惑になります。より効率的な方法は、リテラルを使用して同じ目的を達成することです。
文字通りの借用方法を使用します
リテラルはJavaScriptルールに続く構文構造であり、MDNは次のように説明します。
JavaScriptでは、リテラルを使用すると値を表すことができます。これらは、変数の固定値であるか、文字通りスクリプトに与えられます。
リテラルはプロトタイプとして省略できます。
[] .slice.call(arguments); []。join.call( 'abc'、 '|'); ''。touppercase.call(['lowercase'、 'words'、 'in' in '、' a '、' ante '])。split('、 ');
これはそれほど冗長ではないように見えますが、[]と「」で直接操作する必要があるのはまだ少し醜いです。変数を使用して、リテラルとメソッドへの参照を保存できます。これにより、以下を簡単に作成できます。
var slice = [] .slice; slice.call(arguments); var join = [] .jein; join.call( 'abc'、 '|'); var touppercase = '' .touppercase; touppercase.call(['lowercase'、 'words'、 'in'、 'a'、 'ante'])。split( '、');
メソッドを借り入れることを参照すると、コードを再利用することもできます。冗長性を減らすという原則を順守して、呼び出すたびにcall()またはapply()を書くことなくメソッドを借りることができるかどうかを見てみましょう。
var slice = function.prototype.call.bind(array.prototype.slice); slice(arguments); var join = function.prototype.call.bind(array.prototype.join); join( 'abc'、 '|'); var touppercase = function.prototype.call.bind(string.prototype.touppercase); touppercase(['lowercase'、 'words'、 'in'、 'a'、 'centent'])。分割( '、'));
ご覧のとおり、 Function.prototype.call.bindを使用して、異なるプロトタイプから「借りた」メソッドを静的に結合できるようになりました。しかし、文はどのようvar slice = Function.prototype.call.bind(Array.prototype.slice)どのようにして機能しますか。
function.prototype.call.bindを理解します
Function.prototype.call.bind 、一見すると少し複雑に見えるかもしれませんが、それがどのように機能するかを理解するのは非常に役立ちます。
Function.prototype.callは、関数を「呼び出す」という参照であり、関数で使用するための「この」値を設定します。
「バインド」は、「この」値で新しい関数を返すことに注意してください。したがって、 .bind(Array.prototype.slice)によって返される新しい関数の「この」は、常にarray.prototype.slice関数です。
要約すると、新しい関数は「呼び出し」関数を呼び出し、その「この」は「スライス」関数です。 Slice()を呼び出すと、以前に適格な方法が指されます。
オブジェクトをカスタマイズする方法
継承は優れていますが、開発者は通常、オブジェクトまたはモジュール間のいくつかの一般的な機能を再利用する場合に使用します。ほとんどの場合、単純な借用方法は複雑になる可能性があるため、コードの再利用のためだけに継承を使用する必要はありません。
以前にネイティブの方法を借りることについてのみ議論しましたが、いかなる方法も借りることは問題ありません。たとえば、次のコードは、ポイントゲームのプレーヤースコアを計算できます。
var scorecalculator = {getsum:function(results){var score = 0; for(var i = 0、len = results.length; i <len; i ++){score = score+results [i]; } returnスコア; }、getScore:function(){return scorecalculator.getSum(this.results) / this.handicap; }}; var player1 = {結果:[69、50、76]、ハンディキャップ:8}; var player2 = {結果:[23、4、58]、ハンディキャップ:5}; var score = function.prototype.call.bind(scorecalculator.getScore); //スコア:24.375Console.log( 'スコア:' +スコア(player1)); //スコア:17Console.log( 'スコア:' +スコア(player2));上記の例は非常に鈍いですが、ネイティブの方法と同様に、ユーザー定義の方法を簡単に借りることができることがわかります。
要約します
呼び出し、バインド、および適用は、関数が呼び出される方法を変えることができ、関数を借りるときによく使用されます。ほとんどの開発者は、ネイティブの方法を借りることに精通していますが、カスタム方法を借りることはめったにありません。
近年、JavaScriptの機能プログラミングはよく発展しています。 function.prototype.call.bindを使用する方法は、より便利ですか?このようなトピックはますます一般的になると推定されています。
上記は、JavaScriptの借入方法の概要です。誰もがJavaScriptの借入方法を理解することが役立つことを願っています。