JavaScript で定義されている一般的な関数の違いは、主に次の 3 つの側面を通じて説明されています。必要な場合は参照してください。
1: キーワード関数を呼び出して
を構築します
例:
function distance(x1,x2,y1,y2) { var dx=x2-x1; var dy=y2-y1; return Math.sqrt(dx*dx+dy*dy); }
2: Function() コンストラクターを使用します
例:
var f=new Function*"x","y","return x*y");
このコード行は、使い慣れた構文を使用して定義された関数と本質的に同等の新しい関数を作成します。
function f(x,y) { return x*y; }
コンストラクター Function() に渡されるパラメーターは、作成する関数の名前を指定していないことに注意してください。 Function() コンストラクターで作成された名前のない関数は、「匿名関数」と呼ばれることもあります。
Function() コンストラクターが何に使用されるのか知りたいと思われるかもしれません。関数ステートメントを使用してすべての関数を定義できないのはなぜでしょうか?その理由は、Function() コンストラクターを使用すると、関数ステートメントのプリコンパイルされた関数本体に制限されることなく、関数を動的に構築およびコンパイルできるためです。この副作用として、関数が呼び出されるたびに、Function() コンストラクターがその関数をコンパイルする必要があることです。したがって、ループ本体や頻繁に使用される関数内でこのコンストラクターを頻繁に呼び出すべきではありません。
Function() コンストラクターを使用するもう 1 つの理由は、関数をステートメントとして定義するのではなく、JavaScript 式の一部として定義できることです。
3: 関数リテラル
関数リテラルは、匿名関数を定義できる式です。関数リテラルの構文は、関数ステートメントの構文とよく似ていますが、ステートメントではなく式として使用され、関数名を指定する必要がない点が異なります。次の 3 行のコードは、function() ステートメント、Function() コンストラクター、および関数リテラルを使用して、基本的に同じ 3 つの関数を定義します。
function f(x){return x*x}; var f=new Function("x","return x*x;"); var f=function(x){reurn x*x};
例:
var f=function fact(x){if(x<=1)return 1;else return x*fact(x-1);};
関数リテラルの使用法は、Function() コンストラクターを使用して関数を作成する方法と非常に似ています。これらはステートメントではなく JavaScript 式によって作成されるため、特に一度だけ使用され、名前を付ける必要のない関数の場合、使用方法はより柔軟になります。たとえば、関数リテラル式を使用して指定された関数は、変数に格納したり、他の関数に渡したり、直接呼び出すこともできます。
和Function()构造函数一样,函数直接量创建的是未命名函数,而且不会自动地将这个函数存储在属性中。但是,比起Function()构造函数来说,函数直接量有一个重要的优点。由Function()构造函数创建的函数的主体必须用一个字符串说明,用这种方式来表达一个长而复杂的函数是狠笨拙的。但是函数直接量的主体使用的却是标准的JavaScript语法。而且函数直接量只被解析一次,而作为字符串传递给Function()构造函数的JavaScript代码则在每次调用构造函数时只需被解析一次和编译一次。
在JavaScript1.1中,可以使用构造函数Function()来定义函数,在JavaScript1.2和其后的版本中,还可以使用函数直接量来构造函数。你应该注意这两种方法之间的重要差别。
首先,构造函数Function()允许在运行时动态地创建和编译JavaScript代码。但是函数直接量却是函数结构的一个静态部分,就像function语句一样。
其次,作为第一个差别的必然结果,每次调用构造函数Function()时都会解析函数体并且创建一个新东汉数对象。如果对构造函数的调用出现在一个循环中,或者出现在一个经常被调用的函数中,这种方法的效率非常低。另一个方面,函数直接量或出现在循环和函数中的嵌套函数不是在每次调用时都被重新编译,而且每当遇到一个函数直接量时也不创建一个新的函数对象。
Function()构造函数和函数之间量之间的第三点差别是,使用构造函数Function()创建的函数不使用词法作用域,相反的,它们总是被当作顶级函数来编译,就像下面代码所说明的那样:
var y="global"; function constructFunction() { var y="local"; return new Function("return y");//不捕捉局部作用域。 } //这行代码将显示"global",因为Function()构造函数返回的函数并不使用局部作用域。 //假如使用一个函数直接量,这行代码则可能显示"local"。 alert(constructFunction());