はじめに
JavaScriptのfunction命令は、コードを解析/コンパイルするタイミングで、関数を登録しているらしい。
つまり、function命令は、実行時にはすでにコード内の構造の一部となっているので、同じかそれ以下のスクリプトブロック(<script>)内であれば、関数を宣言する行より前でも関数を呼び出すことができる。
三角形の面積を求める関数を作成
まずは、普通に三角形を求める関数を作成する。
<!--jsを読み込むためのhtml-->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src=./triangle.js></script> <!--読み込むjs-->
</body>
</html>
function getTriangle(base, height){
return base*height/2;
}
console.log(getTriangle(5, 2)); //5
function命令より前で関数を呼び出してみる
console.log(getTriangle(5, 2)); //5←呼び出せる。
function getTriangle(base, height){
return base*height/2;
}
異なるスクリプトブロックから呼び出してみる。
<!--jsを読み込むためのhtml-->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="./test.js"></script><!--新しく読み込むjs-->
<script src=./triangle.js></script>
</body>
</html>
// console.log(getTriangle(5, 2)); コメントアウトします
function getTriangle(base, height){
return base*height/2;
}
console.log(getTriangle(5, 2)); //ここから呼び出します。
結果
test.js:1 Uncaught ReferenceError: getTriangle is not defined
at test.js:1
呼び出せなかった。なぜならブラウザは<script>要素の単位で、順にスクリプトを処理していくためである。※同じスクリプトかtriangle.jsより下の行であれば呼び出せる。
function命令ではなく、関数リテラルやfunctionコンストラクタの場合はどうか
関数リテラル
console.log("getSankaku:"+getSankaku(5, 2));
var getSankaku = function(base, height){
return base*height/2;
};
//Uncaught TypeError: getSankaku is not a function
frunctionコンストラクタ
console.log("getDreieck:"+getDreieck(5, 2));
getDreieck = new Function('base', 'height', 'return base*height/2');
//Uncaught TypeError: getDreieck is not a function
両方ともエラーになる。理由はfunction命令とは異なり、関数リテラルとFunctionコンストラクタは共に実行時に評価されるからである。
まとめ
function命令は静的な構造を宣言するため(解析の時点で関数を登録している)、同じかそれ以下のスクリプトブロック内であれば、どこからでも呼び出せる。
関数リテラル及びFunctionコンストラクタは動的に呼び出されるため、(実行時に評価される)必ず関数を宣言した後でなければ呼び出すことが出来ない。
参考
JavaScript本格入門