この記事では、JavaScriptのさまざまな一般的な関数定義方法について詳しく説明し、参照のために共有されています。特定の分析は次のとおりです。
まず、JavaScriptの4つの最も一般的な関数定義を見てみましょう。
関数コンストラクターで定義された関数、コードは次のとおりです。
var multiply = new function( 'x'、 'y'、 'return x * y;');
関数宣言、この方法も最も一般的です。
関数乗算(x、y){return x * y;}匿名関数として宣言され、変数に割り当てられた関数式は、非常に一般的な方法です。
var multiply = function(x、y){return x * y;}関数式ですが、関数宣言は名前付き関数であり、変数に値を割り当てます。これはまったく同じように見えます。
var multiply = function multi(x、y){return x * y;}まず、関数名と関数に割り当てられた関数変数間の直接的な関係を比較しましょう。それは本当に少しです...より直感的になるために、例4から今、それは関数変数のマルチプリと関数名マルチとの関係です:
それどころか、関数名を変更することはできませんが、関数変数を再割り当てすることができます。関数変数を再割り当てできることを理解するのは簡単です。私たちの4番目の例では、定義されたばかりの多重変数は、それを見るのは楽しいことではありません。
倍数= function(x、y){return x + y;}私はすぐに乗算から加算に変身しました。ただし、マルチ関数変数を変更することは不可能です。関数定義はすでにそこにあります。まだ参照を保持している限り、変更されません。ここで理解するのは簡単ではないかもしれません。最初にこのように考えて、見下ろすと、ゆっくりと理解できるはずです。
関数名は、関数の外側で同時に使用することはできません。関数本文内にのみ表示されます。非常に簡単な例:
var foo = function bar(){alert( 'hello');} foo(); //プロンプト "hello" string bar(); //エラーを実行すると、バーは定義されていませんそして明らかに、ここのバーは実際に関数名ですが、実際には外部的に呼ぶことはできません。現時点では、例4のように、この例がまだ行方不明に見えるのか、例2の方法を使用してみませんか?良い質問、ゆっくりと分解させてください。
例4を続けて、関数名(マルチ)と関数変数(マルチプリ)が同じではないことがわかりますが、実際には2つはまったく関係がないため、一貫性を維持する必要はありません。これについて言えば、上記の4つの例を3に減らし、例2と例4は本質的に一貫しているべきだと思います。なんて、それを信じないの? hehe、私はそれを沈黙させ続けなければなりません〜読み続けてください~~
例2および例4と比較して、VAR関数変数は少ないものであることがわかりましたが、例3と比較して、その関数名は少ないです。現象の観点から見ると、例2と例4の本質は同じであり、証拠は次のとおりです。
function foo(){} alert(foo); //「foo」var bar = foo; alert(bar)を含む関数名をプロンプトします。 //関数名はまだ「foo」のみを含み、barと関係がありませんそれは確かにアイアンクラッドですか?例4のコードと組み合わせて、例2と同様の上記のコードを書く方法ですか?正しい、これは私がちょうど2つが本質的に同じであるべきだと言ったことです。ただし、ケース2の関数を定義するとき、JSエンジンは、関数名をマルチップして関数を宣言したり、Multiplyと呼ばれる変数を静かに定義したり、この変数に割り当てたり、2つの同じ名前を定義したりするのに役立ちました。関数名の掛け算を使用すると、実際に関数変数の増殖を使用していたので、めまいがしていたので、正直に言って、私はめまいがしました。要するに、私たちは実際に関数変数を呼び出したときに、関数名を外部的に呼び出すことができなかったので、上記の推論がありました。
ただし、ここで言及する小さな違いは、関数宣言方法によって定義される関数がコンストラクター宣言または関数式宣言とは異なることです。関数宣言法は、関数定義の前に呼び出すことができます...言うまでもなく、コードを見てください。
foo(); // foofunction foo(){alert( 'foo');} bar(); //バディ、それは上記とは本当に違うので、見せびらかしてはいけません。これは間違いではありませんか?プロンプトバーは定義されていませんvar bar = function(){alert( 'bar');}コンストラクターによって宣言された機能について話しましょう。宣言された関数は、現在宣言された場所の範囲を継承しません。デフォルトではグローバルな範囲のみがあります。ただし、これは次のように、他の関数宣言方法でも同じです。
function foo(){var hi = 'hello'; // return function(){// alert(hi); //}; return function( 'return hi;');} foo()(); //実行効果については、自分で実行して確認してください変数HIがその範囲(つまり、グローバルスコープ)にないため、コンストラクター宣言を使用して返される関数の実行が必然的にエラーを報告することを想像できます。
もう1つの点は、コンストラクターモードで宣言された関数が非効率的であると人々が言うことです。なぜこれがなぜですか?今日、私は文書から、他の3つの方法で宣言された関数が一度だけ解析されることを学びました。実際、それらは閉鎖に存在しますが、それはスコープチェーンにのみ関連しており、関数本体は一度だけ解析されます。しかし、コンストラクターの方法は、関数が実行されるたびに、その関数本体が一度解析されることです。このように宣言された関数は、パラメーターと関数本体を保存するオブジェクトであると考えることができます。実行されるたびに、1回解析する必要があり、パラメーターと関数本体が実行されます。これは必然的に非効率的です。特定の実験を行う方法がわかりませんか?
最後に、誰も注意を払わないことについて話しましょう。機能宣言の命令は、機能の寿命ではなく、機能の宣言のように思われるのはいつですか(例2の方法が不注意に別の方法になるとき、それを簡単に言えばとても傾いています):
式の一部になると、例3と例4のようになります。
これは、スクリプト自体または関数の「ソース要素」ではなくなりました。ソース要素は何ですか?つまり、スクリプトまたは関数本文の非ネストステートメントまたは次のようなものです。
var x = 0; //ソース要素if(x == 0){//ソース要素x = 10; //ソース要素ではありません。IFステートメント関数BOO(){}にネストされているため、ソース要素ではありません。IFステートメントにネストされているため} function foo(){//ソース要素var y = 20; //ソース要素関数bar(){} //ソース要素while(y == 10){//ソース要素関数blah(){} //ソース要素ではありません。 //ソース要素ではありません。なぜなら、それはしばらくの声明にネストされているからです}}ソース要素の概念を大まかに理解しています。私は今言及した機能宣言を続けます。参照してください:
// function宣言関数foo(){} // function expression(function bar(){})// function expression x = function hello(){} if(x){//関数function world(){}} //関数ステートメントa(){// functionステートメント関数b(){} if最後に、私自身の理解について話させてください。関数宣言と非機能宣言を区別する理由は、私の見解では、JS解析エンジンがそれを実行するときに、関数宣言の関数定義が事前に宣言されるためです。つまり、上記のように、関数定義の前に使用できます。実際、解析エンジンはそれを使用する前に解析しました。ただし、発現関数宣言など、非機能宣言は、JS解析エンジンは、VARが事前に宣言された変数を定義します。この時点で、変数値は定義されていません。この変数への実際の割り当ては、コードの実際の場所にあります。したがって、上記のエラーはすべて未定義です。実際の変数は定義されていますが、まだ割り当てられていません。 JS解析エンジンは、それが機能であることを知りません。
この記事の説明には、全員のJavaScript Webプログラミングデザインの特定の参照値があると思います。