いくつかの簡単なJavaScript操作では、呼び出しおよび適用機能がめったに使用されません。 Webアプリケーション開発などの他の大規模な操作では、これら2つの機能はJSフレームワーク開発で頻繁に発生する可能性があります。これら2つの機能の説明に関する多くの情報もありますが、多くの情報が書かれているか、非常に類似しており、現実的な説明がないと思います。次に、これらの2つの機能をより明確でシンプルなアイデアで分析および説明しようとします。
コードコピーは次のとおりです。
call()およびapply()を特定のオブジェクトのメソッドと見なし、メソッド実装を呼び出すことにより間接的に関数を呼び出すことができます。 call()およびapply()の最初の引数は、関数を呼び出す親オブジェクトです。これは呼び出しのコンテキストであり、関数本文でこれを通してそれを参照します。オブジェクトoのメソッドで関数f()を呼び出すには、call()とapply()を使用して次のように使用できます。f.call(o)f.apply(o)。[1]
最初に通話を分析しましょう。 ECMAScript第3版[2]によるコール関数の説明は次のとおりです。関数オブジェクト(func.call(0))によってコールメソッドが呼び出される場合、必要なパラメーターといくつかの非必須パラメーターを渡す必要があります。その実行プロセスは次のとおりです。
a、呼び出しを呼び出すオブジェクトが実行されていない場合、タイプエラーエラーがスローされます。
b、パラメーターリストを空に設定します
C、呼び出されたメソッドが複数のパラメーターを渡す場合、arg1、arg2 ...をパラメーターリストに順番に挿入します
Dは、呼び出しの結果を返し、これを通話関数(FUNC)に渡されたパラメーター1に置き換え、渡されたパラメーターリストをこの関数のパラメーターとして扱います。
実際、呼び出し関数は関数オブジェクトのプロトタイプです。つまり、呼び出す関数も関数でなければなりません。この呼び出しを呼び出すときは、オブジェクトを通過して呼び出しを呼び出す関数にこれを置き換えてください。これが例です:
<script> function c1(){this.name = 'zhang san'; this.age = '24 '; this.sayname = function(){console.log( "これはc1クラスです、私の名前は"+this.name+"私の年齢は"+this.age); }} function c2(){this.name = 'li si'; this.age = '25 '; } var c1 = new C1(); var c2 = new C2(); c1.sayname(); c1.sayname.call(c2); </script>実行結果:
これがC1カテゴリです、私の名前は次のとおりです。
これがC1カテゴリです、私の名前は次のとおりです。LiSi私の年齢は25歳です
上記のコードでは、C1とC2の2つのクラスが宣言されています。 C1には2つのプロパティ、1つの方法があり、C2にはC1と同じ2つのプロパティがあります。インスタンス化後、c1.sayname()は実際のプロパティを印刷しますが、c1.sayname.call(c2)はc2のプロパティを印刷します、なぜこれはなぜですか? SayName()は関数であり、関数本文にこれがあるため、コールが実行されると、これはC2に置き換えられるため、C2の属性が最終的に印刷されます。
適用と呼び出しの違いは、オプションのパラメーターの通過にあります。適用のすべてのオプションパラメーターは、1つのパラメーターが入力されるため、配列に保存され、コールは複数のパラメーターに渡されます。
それでは、適用関数と通話機能のアプリケーションは何ですか? 1つ目は、ネットワーク上の数値配列内の最大の要素を見つけることです。 Math.max.apply(null、array)を直接使用できます。もう1つは、次のように、応募と呼び出しを使用することです。
<script> function human(name、sex){this.name = name; this.sex = sex; this.walk = function(){console.log( '私は歩いている'); }} function child(){human.call(this、 "xiao ming"、 "male")this.paly = function(){console.log( '私はとてもプレイするのが好きです'); } this.intruduce = function(){console.log( 'こんにちはみんな、i'+this.name); }} var jinp = new Human( 'jack'、 'male'); var xiaoping = new Child(); xiaoping.walk(); xiaoping.paly(); xiaoping.intruduce(); </script>実行結果:
私は歩いています
私はとても遊ぶのが好きです
みなさん、こんにちは、私はXiao Mingです
call()およびapply()がbind()に同様の関数は、ecmascript 5に追加された新しい方法ですが、ecmascript 3で簡単にシミュレートできます。bind関数は、javascriptのfunction.prototypeメソッドでもあります。この方法の主な内容は、関数をオブジェクトに結合することです。 bind()メソッドが関数f()にバインドされ、オブジェクトoがパラメーターとして渡されると、このメソッドは新しい関数を返し、oの方法と呼ばれます。新しい関数に渡された引数は、元の関数に渡されます。次のように:
<script>関数はじめに(国、趣味){"return" Helloみんな、私の名前は "+this.name+"、今年 "+this.age+" from "+country+"、like "+bobby; } var xiaoming = {name: "xiao ming"、age:20} var jieshao = introduce.bind(xiaoming); console.log(jieshao( "china"、 "playing ball")); </script>実行結果:
みなさん、こんにちは、私の名前はXiao Mingです、私は20歳です、中国出身です。バスケットボールをするのが好きです
上記の例は次のと同等です。
<script>関数はじめに(国、趣味){"return" Helloみんな、私の名前は "+this.name+"、今年 "+this.age+" from "+country+"、like "+bobby; } var xiaoming = {name: "xiaoming"、age:20} console.log(introws.apply(xiaoming、["china"、 "play"])); //またはconsole.log(indute.call(xiaoming、 "china"、 "play")); </script>ECMAScript 5の厳格なモードでは、Call()とApply()の最初の実際の引数は、実際の引数で渡されたものが元の値であるか、nullまたは未定義である場合でも、この値になります。 ECMAScript 3および非強制モードでは、渡されたnullと未定義はグローバルな対立に置き換えられ、他の元の値は対応するラッパーオブジェクトに置き換えられます。
参照
[1]、権威あるJavaScriptガイド、第6版、189ページ
[2]、function.prototype.call(thisarg [、arg1 [、arg2、…]])
[3]、function.prototype.apply(thisarg、argarray)