関数はモジュール型プログラミングの基礎です。複雑な Ajax アプリケーションを作成するには、関数をより深く理解する必要があります。
JavaScript の関数は他の言語とは異なり、各関数はオブジェクトとして保持され、実行されます。関数オブジェクトのプロパティを使用すると、関数を変数に割り当てたり、関数をパラメーターとして渡すことが簡単にできます。続行する前に、関数を使用する構文を見てみましょう:
以下は引用部分です:
function func1(…){…}
var func2=function(…){…};
var func3=function func4(…){…};
var func5=new Function();
これらは関数を宣言するための正しい構文です。これらは、他の言語の一般的な関数や、以前に紹介した関数の定義方法とは大きく異なります。では、なぜ JavaScript でこのように記述できるのでしょうか?それはどのような構文に従いますか?これらについては以下で説明します。
関数オブジェクトについて
function キーワードを使用して関数を定義し、各関数に関数名を指定し、関数名を通じてその関数を呼び出すことができます。 JavaScript が解釈されて実行されるとき、関数はオブジェクトとして保持されます。これが、導入される Function オブジェクトです。
関数オブジェクトは他のユーザー定義オブジェクトとは本質的に異なります。このタイプのオブジェクトは内部オブジェクトと呼ばれます。たとえば、日付オブジェクト (Date)、配列オブジェクト (Array)、および文字列オブジェクト (String) はすべて内部オブジェクトです。 。 物体。これらの組み込みオブジェクトのコンストラクターは JavaScript 自体によって定義されます。 new Array() などのステートメントを実行してオブジェクトを返すことにより、JavaScript にはユーザーがオブジェクトの構築方法を指定する代わりに、返されたオブジェクトを初期化する内部メカニズムがあります。 。
JavaScript では、配列オブジェクトの対応するタイプが Array で、日付オブジェクトの対応するタイプが Date であるのと同じように、関数オブジェクトの対応するタイプは Function です。関数オブジェクトは new Function() を通じて作成することもできます。関数キーワードを使用してオブジェクトを作成します。理解を容易にするために、関数オブジェクトの作成と配列オブジェクトの作成を比較します。まず配列オブジェクトを見てみましょう。 次の 2 行のコードはどちらも配列オブジェクト myArray を作成します。
以下は参照フラグメントです。
var myArray=[]
//
と同等です。 var myArray=new Array ();
同様に、次の 2 つのコードでも関数 myFunction を作成します。
function myFunction(a,b){
return a b; /
var myFunction=new Function("a","b","return a b");
と同等 配列オブジェクトを構築する文と比較すると、関数の本質がよくわかります。前に紹介した関数宣言は、上記のコードの最初の方法で、インタープリター内でこの構文に遭遇すると、Function オブジェクトが自動的に構築され、関数が内部オブジェクトとして保存されて実行されます。ここから、関数オブジェクト名 (関数変数) と通常の変数名は同じ仕様であることがわかります。どちらも変数名を通じて変数を参照できますが、関数変数名の後に括弧とパラメーターを続けることができます。関数呼び出しを実行するリスト。
new Function() の形式で関数を作成することは一般的ではありません。通常、関数本体に複数のステートメントが含まれており、それらのステートメントが文字列の形式でパラメーターとして渡されると、コードの可読性が低下します。 。以下はその使用構文の概要です:
以下は参照フラグメントです:
var funcName=new Function(p1,p2,...,pn,body);
パラメータのタイプは次のとおりです。 p1 から pn までのすべての文字列は作成された関数のパラメータ名のリストを表し、body は作成された関数の関数本体ステートメントを表し、funcName は作成された関数の名前を表します。パラメータを指定せずに空の関数を作成したり、funcName を指定せずに名前のない関数を作成したりすることもできます。もちろん、そのような関数には意味がありません。
p1 から pn はパラメーター名のリストであることに注意してください。つまり、p1 はパラメーターを表すだけでなく、カンマで区切られたパラメーターのリストにすることもできます。たとえば、次の定義は同等です。 >以下は参照フラグメントです:
new Function("a", "b", "c", "return a b c")
new Function("a, b, c", "return a b c")
new Function("a,b", "c", "return a b c")
JavaScript は Function タイプを導入し、new Function() などの構文を提供します。これは、関数オブジェクトがプロパティやプロパティを追加するには Function タイプを使用する必要があるためです。メソッド。
関数の本質は内部オブジェクトであり、JavaScript インタプリタがその動作方法を決定します。上記のコードで作成した関数は、プログラム内で関数名を使用して呼び出すことができます。このセクションの冒頭に挙げた関数定義の問題についても説明します。関数宣言の直後に括弧を追加して、関数が作成直後に呼び出されることを示すことができることに注意してください。例:
以下は参照フラグメントです:
var i=function (a,b){
return a b;
}(1,2);
alert(i);
このコードは、変数 i の値が 3 であることを表示します。 i は、作成された関数ではなく戻り値を表します。これは、括弧 "(" が等号 "= よりも優先順位が高いためです。このようなコードは一般的には使用されないかもしれませんが、ユーザーが使用したい場合にはこれがモジュラーの良い解決策です。デザインの場合や、名前の競合を避けたい場合に使用します。
関数を作成する次の 2 つの方法は同等であることに注意してください:
以下は参照フラグメントです:
function funcName(){
//関数本体
}
//
var funcName=function(){
//関数本体
}
と同等ですが、前者のメソッドは名前付き関数を作成するのに対し、後者のメソッドは名前のない関数を作成します。この名前のない関数を指す変数。使用上の違いは 1 つだけです。名前付き関数の場合は呼び出し後に定義できますが、名前のない関数の場合は呼び出す前に定義する必要があります。例:
以下は引用部分です:
は正しく実行でき、次のステートメントも正しく実行できます。
以下は引用部分です。
JavaScript はインタープリタ言語ですが、コード全体に対応する関数定義があるかどうかをチェックすることがわかります。この関数名は関数 funcName() の形式で定義された関数のみが有効であり、匿名関数は無効です。
関数オブジェクトと他の内部オブジェクトの関係
関数オブジェクトに加えて、Object、Array、Date、RegExp、Math、Error など、多くの内部オブジェクトがあります。これらの名前は実際には型を表しており、new 演算子を通じてオブジェクトを返すことができます。ただし、関数オブジェクトは他のオブジェクトとは異なります。typeof を使用して関数オブジェクトの型を取得する場合は、引き続き文字列 "function" を返します。また、配列オブジェクトまたはその他のオブジェクトの typeof を使用する場合は、文字列 "object" を返します。 」。次のコードは、typeof のさまざまなタイプを示しています。
以下は参照フラグメントです。
alert(typeof(new Function())); ( typeof(Array));
alert(typeof(new Array()));
alert(typeof(new Date())); ( typeof(new Object()));
このコードを実行すると、最初の 4 つのステートメントは「function」を表示し、次の 3 つのステートメントは「object」を表示することがわかります。 function は実際には function を返します。これは他のオブジェクトとは大きく異なります。 Array や Object などの他の型は、new 演算子を通じて通常のオブジェクトを返します。関数自体もオブジェクトですが、オブジェクト コンストラクターでもあるため、通常のオブジェクトとは異なります。つまり、以前に紹介したオブジェクトを返す新しい関数を作成できます。 typeof が「function」を返すオブジェクトはすべて関数オブジェクトです。このようなオブジェクトはコンストラクターとも呼ばれます。したがって、すべてのコンストラクターがオブジェクトですが、すべてのオブジェクトがコンストラクターであるわけではありません。
関数自体もオブジェクトなので、その型は function です。C や Java などのオブジェクト指向言語のクラス定義を考えると、Function 型の役割が推測できます。関数オブジェクト自体のいくつかのメソッドと属性を定義すると、関数のプロトタイプ オブジェクトを使用して、関数型の定義を簡単に変更および拡張できます。たとえば、関数型 Function は以下のように拡張され、method1 メソッドが拡張されます。この機能は、「function」を表示するダイアログ ボックスをポップアップすることです。
以下は引用部分です:
Function.prototype.method1=function(){
alert("function") );
}
関数 func1(a,b,c){
return a b c;
func1.method1.method1(); 🎜> 最後のステートメント: func1.method1.mehotd1() に注目してください。これは、関数オブジェクトメソッド 1 のメソッド 1 を呼び出します。少し混乱しているように見えますが、構文を詳しく見ると、これが再帰的定義であることがわかります。 Method1 自体も関数であるため、関数オブジェクトのプロパティとメソッドも持ちます。Function 型へのすべてのメソッド拡張には、このような再帰的なプロパティがあります。
Function はすべての関数オブジェクトの基礎であり、Object はすべてのオブジェクト (関数オブジェクトを含む) の基礎です。 JavaScript では、すべてのオブジェクトは Object のインスタンスであるため、すべてのオブジェクトがいくつかの共通のプロパティとメソッドを持つようにオブジェクト タイプを変更できます。
以下は参照フラグメントです。 🎜>Object.prototype.getType=function(){
return typeof(this);
var array1=new Array();
function func1(a,b){
return a b;
}
alert(array1.getType());
alert(func1.getType());
上記のコードは、すべてのオブジェクトに getType メソッドを追加します。このオブジェクトのタイプ。 2 つのアラート ステートメントには、それぞれ「オブジェクト」と「機能」が表示されます。
関数をパラメータとして渡す
関数オブジェクトの本質を前に紹介しました。各関数は変数に簡単に割り当てることができる特別なオブジェクトとして表現され、この変数名を通じて関数呼び出しが行われます。 。変数として、パラメータの形式で別の関数に渡すことができます。これは、JavaScript イベント処理メカニズムの以前の紹介で見られました。たとえば、次のプログラムは func1 をパラメータとして func2 に渡します。以下は引用スニペットです:
function func1(theFunc){
theFunc();
function func2(){
alert("ok"); func1( func2);
最後のステートメントでは、func2 がオブジェクトとして func1 の仮パラメータ theFunc に渡され、func1 によって内部的に theFunc が呼び出されます。実際、関数をパラメータとして渡すこと、または関数を他の変数に割り当てることは、すべてのイベント メカニズムの基礎です。
たとえば、ページの読み込み時に初期化作業を実行する必要がある場合は、最初に init 初期化関数を定義し、次に window.onload=init; ステートメントを通じてそれをページ読み込み完了イベントにバインドします。ここでの init は関数オブジェクトであり、ウィンドウの onload イベント リストに追加できます。
関数に渡される暗黙的なパラメーター: 引数
関数呼び出しが行われると、指定されたパラメーターに加えて、暗黙的なオブジェクト (引数) も作成されます。 argument は配列に似ていますが、配列ではないオブジェクトです。arguments[index] などの構文を使用して値を取得するために使用でき、配列を持っているため似ています。 length 属性の長さ。引数オブジェクトには、関数に実際に渡されるパラメータが格納されます。これは、関数宣言で定義されたパラメータ リストに限定されません。次に例を示します。
以下は参照フラグメントです。
function func(a,b){
alert(a);
alert(b);
for(var i=0;i
}
func(1,2,3);
コードが実行されると、1、2、1、2、3 の順に表示されます。したがって、関数を定義する際にパラメータリストを指定しなくても、取得したパラメータを引数を通じて参照できるため、プログラミングに大きな柔軟性がもたらされます。引数オブジェクトのもう 1 つの属性は callee で、これは関数オブジェクト自体への参照を表します。これは、名前のない関数の再帰を実装したり、関数のカプセル化を保証したりする場合に役立ちます。たとえば、再帰を使用して 1 から 1 までの自然数の合計を計算します。 n:
以下は参照フラグメントです:
var sum=function(n){
if(1==n)return 1;
else return n sum(n-1); 🎜>}
alert( sum(100));
関数には sum 自体の呼び出しが含まれていますが、JavaScript の場合、関数名は関数内での sum の呼び出しと同じです。グローバル変数ですが、これはあまり良くありません。リフレクションはそれ自体を呼び出すことなので、arguments.callee 属性を使用する方が良い方法です。
以下は参照フラグメントです:
var sum=function(n){
if(1==n) return 1;
else return n argument.callee(n-1);
alert(sum(100));以下に示すように、引数が配列オブジェクトと異なる唯一の機能ではありません。このコードは、引数が Array 型から作成されないことを示しています。
以下は参照フラグメントです。
Array.prototype.p1=1; 🎜>alert(new Array().p1);
function func() {
alert(arguments.p1);
func(); コードを実行すると、最初のアラートステートメントが 1 と表示されていることがわかります。これは、配列オブジェクトが属性 p1 を持っていることを意味し、func 呼び出しは「未定義」と表示されます。つまり、p1 は引数のプロパティではないことがわかります。引数が配列オブジェクトではないこと。
関数の apply、call メソッド、および length 属性
JavaScript は、関数オブジェクトに対して apply と call という 2 つのメソッドを定義します。これらの機能は、実行のために関数を別のオブジェクトにバインドすることです。パラメータの方法が異なります。 🎜>以下は参照フラグメントです:
Function.prototype.apply(thisArg,argArray);
Function.prototype.call(thisArg[,arg1[,arg2…]]);関数プロトタイプからわかるように、最初のパラメーターの名前は thisArg です。つまり、すべての関数内の this ポインターには thisArg が割り当てられ、これにより関数を別のオブジェクトのメソッドとして実行するという目的が達成されます。 thisArg パラメータを除き、どちらのメソッドも Function オブジェクトに渡されるパラメータです。次のコードは、apply メソッドと call メソッドがどのように機能するかを示しています。
以下は参照フラグメントです:
//属性 p とメソッド A を持つ関数 func1 を定義します。
function func1(){
this. p="func1-";
this.A=function(arg){
alert(this.p arg)
}
}
// 属性 p を使用して関数 func2 を定義します。メソッド B
function func2(){
this.p="func2-";
this.B=function(arg){
alert(this.p arg);
}
var obj1=new func1();
var obj2=new func2(); //func1-byA
B を表示します。 ("byB"); // func2-byB を表示します
obj1.A.apply(obj2,["byA"]); // func2-byA を表示します。ここで、["byA"] には要素配列が 1 つだけあります。以下同様
obj2.B.apply(obj1,["byB"]); //func1-byB を表示
obj1.A.call(obj2,"byA") //func2-byA を表示
obj2.B.call(obj1,"byB"); //func1-byB を表示
obj1 のメソッド A が obj2 にバインドされて実行された後、関数 A の実行環境全体が obj2 に転送されることがわかります。 obj2、つまり、このポインタは obj2 を指します。同様に、obj2 の関数 B を obj1 オブジェクトにバインドして実行することもできます。コードの最後の 4 行は、apply 関数と call 関数のパラメーター形式の違いを示しています。
引数の長さ属性とは異なり、関数オブジェクトには長さ属性もあります。これは、呼び出し時に実際に渡されるパラメーターの数ではなく、関数の定義時に指定されたパラメーターの数を表します。たとえば、次のコードは 2 を表示します。
以下は参照フラグメントです:
function sum(a,b){
return a b;
}
alert(sum.length) ;
JavaScript の this ポインタを深く理解する
this ポインタは、オブジェクト指向プログラミングにおける重要な概念であり、現在実行中のオブジェクトを表します。オブジェクトのメソッドを実装する場合、このポインターを使用してオブジェクト自体への参照を取得できます。
他のオブジェクト指向言語とは異なり、JavaScript の this ポインターは動的変数です。前のセクションでは、apply と call について説明しました。関数のメソッドにはそのような例がありました。理解を容易にするために、次の例を見てみましょう:
以下は引用部分です:
コードの実行から その結果、それぞれ 1 と 2 を示すダイアログ ボックスが表示されます。 getP 関数は一度だけ定義され、異なる機会に実行され、異なる実行結果を示すことがわかります。これは、このポインタの変化によって決まります。 obj1 の getP メソッドでは、this は obj1 オブジェクトを指し、obj2 の getP メソッドでは、this は obj2 オブジェクトを指し、両方のオブジェクトが持つ属性 p がこのポインタを通じて参照されます。
JavaScript の this ポインターは動的に変化する変数であり、現在関数を実行しているオブジェクトを示していることがわかります。このポインタの性質から、JavaScript におけるオブジェクトの性質をより深く理解することもできます。つまり、オブジェクトは 1 つ以上のプロパティ (メソッド) のコレクションです。各コレクション要素は 1 つのコレクションに属するだけでなく、複数のコレクションに動的に属することもできます。このようにして、メソッド (コレクション要素) を呼び出す人は、this ポインターが指す人を指します。実際、先ほど紹介した apply メソッドや call メソッドは、このポインタの値をパラメータで指定されたオブジェクトを指すように強制的に変更することで実装されており、あるオブジェクトのメソッドを別のオブジェクトのメソッドとして実行します。
各オブジェクト コレクションの要素 (つまり、プロパティやメソッド) も独立した部分です。グローバル関数と変数はウィンドウ オブジェクトのメソッドと見なすことができるため、グローバル関数とオブジェクト メソッドとして定義された関数との間に違いはありません。と属性。 new 演算子を使用してオブジェクトのメソッドを操作し、オブジェクトを返すこともできます。この方法では、オブジェクトのメソッドをクラスの形式で定義でき、this ポインターは新しく作成されたオブジェクトを指すようになります。後でわかるように、このときオブジェクト名は名前空間として機能します。これは、JavaScript を使用したオブジェクト指向プログラミングの手法です。例:
以下は参照フラグメントです:
var namespace1=new Object();
namespace1.class1=function(){
//オブジェクトを初期化するコード
}
var obj1 =new namespace1.class1();
ここでは、namespace1 を名前空間として考えることができます。
オブジェクトの属性 (メソッド) は動的に変化する特性があるため、オブジェクトの 2 つの属性 (メソッド) 間の相互参照は this ポインターを経由する必要がありますが、他の言語では this キーワードを省略できます。上の例のように:
以下は参照フラグメントです:
obj1.getP=function(){
alert(this.p); //表面上、このポインタは obj1 を指します。