Yakim shu Hi, 這是我擴充腦內海馬體的地方。

【筆記】Javascript大全 - 06 函式(一) 函式的定義方法

JavaScript函式有三種定義方法,一般來說前兩種比較常用,分別在效率、解析順序、作用域上都有不同的特性,接下來會解釋他們之間的區別。

// 1. function語句函式
function test1(){ };

// 2. 函式直接賦值變數
var test2 = function() { };

// 3. function建構式函式
var test3 = new Function();

編譯順序比較

對於function語句式的函數,JavaScript解析器會優先的解釋,其後才是一行一行照順序解析

test1();
// "第一種宣告方式:可以先調用再宣告!"
function test1() {
  console.log("第一種宣告方式:可以先調用再宣告!");
}


alert( test2() );
// "TypeError: test2 is not a function"
var test2 = function(){
  console.log("第二種宣告方式:不可以先調用再宣告!");
}

看看以下經典範例來說明解析步驟:

  1. JavaScript解析器,會首先找到第一個test1( ) → 1
  2. 接下來找到第四個test1( ),並蓋掉第一個test1( ) → 4
  3. 再後來沒有function開頭語句了,所以才從頭一行一行執行並回傳
  4. 最後依序回傳 4, 2, 3, 3, 5, 6
function test1() { return 1; }
alert(test1());  // 4 → 被第四個 test1() 蓋掉

var test1 = function() { return 2; };
alert(test1());  // 2 

var test1 = new Function("return 3");
alert(test1()); // 3

function test1() { return 4; }
alert(test1()); // 3 → 第四個已經被解析過了所以跳過

var test1 = function() { return 5; };
alert(test1()); // 5

var test1 = new Function("return 6");
alert(test1()); // 6

效率比較

做一個執行100000次的迴圈,分別測試三種函式的作用時間 ( 可以把個別的註釋拿掉做測試 )
會發現總花費時間: 1 = 2 < 3

var day1 = new Date();
var time1 = day1.getTime();

for(var i=0; i<100000; i++){
  //1.
  //function test1(){}
  
  //2.
  //var test2 = function() {};
  
  //3.
  //var test3 = new Function();
}

var day2 = new Date();
var time2 = day2.getTime();

console.log(time2-time1);

作用域比較

此範例定義3種同名函式,可以把個別註釋拿掉看比較結果。

var k = 1; //全域變數

function fn(){
  var k = 2; //區域變數
  
  // 函式作用域 (回傳 2)-----
  //function test(){ return k; }
  //var test = function() { return k; };
  
  // 頂級作用域 (回傳 1)-----
  //var test = new Function("return k;");
  
  alert(test());
}

fn();

結論

綜合以上比較結果,可以得出3種定義函式的不同

類型 1. function語句 2. 函式直接賦值變數 3. function建構式
名稱 有名 匿名 匿名
性質 靜態 靜態 動態
解析時機 優先 順序解析 順序解析
多次調用效率
作用域 函式作用域 函式作用域 頂級作用域

資料來源:
JavaScript大全(第六版)
【Youtube】尚学堂科技 javascript视频教程 白贺翔 函数【二】三种定义方式