JavaScript で関数を定義するには 2 つの方法があります:
function ftn(){} // 第一种 var ftn = function(){} // 第二种
これら 2 つの記述方法は完全に同等であると言う人もいます。ただし、前者の書き方は解析前にパーサーによって自動的にコードの先頭に昇格されてしまい、関数を定義してから使用するという原則に反するため、後者の書き方を使用することをお勧めします。関数の定義。
この文章を読んで最初に感じたのは、この2つは使い方としては全く同じだけど、分析には違いがあるということです。しかし、「前の書き方はパーサーによって自動的にコードの先頭に昇格される」という彼の説明は私を混乱させました。
そこで、次の最初のテストを行いました:
<script type="text/javascript"> function ftn() { alert('old'); } var b = ftn; function ftn() { b(); alert('new'); } ftn();//浏览器报内存溢出 </script>
次に、2 番目のテストを行いました:
<script type="text/javascript"> var ftn = function() { alert('old'); } var b = ftn; var ftn = function() { b(); alert('new'); } ftn();//old,new依次弹出 </script>
インターネット上の説明は次のとおりです: 最初の方法では、ftn の関数は最初に内部で再定義されていませんでした。 2 番目の方法では、ここでの ftn=function() は Function のコード内で実行されません。ftn は再定義されているため、ここでの再定義は有効です。
それが明確でない場合は、次のように別のテストを実行しました:
<script type="text/javascript"> function ftn() { alert('old'); } var b = ftn; function ftn() { b(); alert('new'); } alert(b);//结果是重新定义的ftn内容 </script>
テストの結果、ftn を再定義すると、b の内容も変更されることがわかりました。次に、さらに 2 つのテストを実行しました:
<script type="text/javascript"> var ftn = function() { alert('old'); } var b = ftn; var ftn = function() { b(); alert('new'); } alert(b);//结果是老的ftn内容 </script>
これは非常に興味深いものです。JavaScript では、基本的なデータ型を除いて、他の型はオブジェクトであり、そのエイリアスはスタックに保存されます。テストはこの原則を使用して明らかに理解できます。では、なぜ ftn の再定義によって前のテスト b が変更されたのでしょうか?
新しい説明があります。それが正しいかどうかはわかりませんが、JavaScript にはメソッドのオーバーロードは存在せず、後で定義された同じ名前の関数は前の関数を上書きします。 var b = ftn; この文は、b と ftn の参照が同じヒープ内のメモリを指すようにします。関数 ftn(){} を再定義すると、新しい関数オブジェクトは古いオブジェクトを上書きしますが、b と ftn によって参照されるヒープ アドレス空間は上書きされます。この場合、この書き方が妥当です:
<script type="text/javascript"> function ftn() { alert('old'); } var b = ftn; var ftn = function() { b(); alert('new'); } alert(b);//老的ftn alert(ftn);//新的ftn ftn();//old ,new </script>
このようにして、スタック内の新しい ftn のアドレスが変更され、新しい関数オブジェクトの定義と元の関数オブジェクトの定義を指します。関数は上書きされず、まだ保存されているため、 b 古い ftn によって参照されるアドレスのままです。
JavaScript の関数を理解するという記事を書きましたが、記事の内容を振り返ってみると、テスト結果の理解にはまだ少し問題があるように感じます。コンパイルと操作の原則に基づいています。 JavaScript はコードの実行時にコードをコンパイルするため、var で定義された型は変数になる可能性があり、カプセル化するオブジェクトにはプロパティやメソッドが追加されることが多いため、この方法で私のタイトルによって引き起こされる問題を理解することができます。変数 var obj = new Object() は、JavaScript でプリコンパイルと呼ばれる非常に初期の処理のみを実行します。このプリコンパイル機能は非常に弱いため、実行に影響を与えることなく任意に変更できます。オブジェクトが呼び出されると、JavaScript インタプリタがコードをコンパイルしてから実行します。これは、Java が最初にコードをコンパイルしてから呼び出されたときに実行するのとは大きく異なります。ほとんどのスクリプト言語は高速ではありません。ただし、fonction ftn(){} のような関数を定義すると、コードがコンパイル、つまり実行されます。この記述方法は Java 関数の定義と非常に似ています。これは私の新しい解釈であり、この説明の方が合理的だと思います。
JavaScript の「コンパイル」は、コード エラーがあるかどうかをチェックするだけであり、コードを実行することはありません。関数内に何かを書いてテストすることができます。プリロード、最初に関数、次に変数。上記のコードでは、demo1とdemo3のみが影響を受けます。demo1とdemo3のソースコードの順序は、関数 - var - function、プリロード適用後の順序: function - function - var、プリロード後の完全なコード:
<script type="text/javascript"> //demo1 function ftn() { alert('old'); } function ftn() { b(); alert('new'); } var b = ftn; ftn();//浏览器报内存溢出 </script>
<script type="text/javascript"> //demo3 function ftn() { alert('old'); } function ftn() { b(); alert('new'); } var b = ftn; alert(b);//结果是重新定义的ftn内容 </script>
preloadingです。それについて。