簡析JavaScript中的Function類型(一)——函數名是指針

提及來ECMAScript中什麼最有意思,用原書(《JavaScript高級程序設計》)做者的話說——莫過於函數了,有意思的根源在於函數其實是對象。每一個函數都是Function類型的實例,並且都與其餘引用類型同樣具備屬性和方法。因爲函數是對象,所以函數名實際上也就是一個指向函數對象的指針,不會與某個函數綁定。javascript

函數的定義方式有三種:java

  1. 函數聲明
  2. 函數表達式
  3. 使用Function構造函數

函數聲明的方式是比較常見的一種,以下面例子所示:安全

function sum(num1, num2){
  return num1 + num2;
}

這與下面使用函數表達式定義函數的方式幾乎相差無幾:函數

var sum = function(num1, num2){
  return num1 + num2;
};

上面的函數表達式語法定義了變量sum,並將其初始化爲一個函數。有讀者可能會注意到,function關鍵字後面沒有函數名,這是由於在使用函數表達式定義函數的時候,沒有必要使用函數名,經過變量sum便可以引用函數。另外,還要注意函數未尾有個分號,就像聲明其它變量同樣。性能

使用Function構造函數定義函數時,Function構造函數能夠接收任意數量的參數,但最後一個參數始終都被看做是函數體,而前面的參數則枚舉出了新函數的參數。來看下面的例子:設計

var sum = new Function('num1', 'num2', 'return num1 + num2');

從技術上講,這也是一個函數表達式。可是,咱們不推薦使用這種方式定義函數,由於這種函數定義方式會致使解析兩次代碼(第一次是解析常規ECMAScript代碼,第二次是解析傳入構造函數中的字符串),從而影響性能。不過,這種方式對於理解「函數是對象,函數名是指針」來講卻是很是直觀的。指針

因爲函數名僅僅是指向函數的指針,所以函數名與包含對象指針的其餘變量沒有什麼不一樣。換句話說,一個函數可能會有多個名字,以下例所示:code

function sum(num1, num2){
  return num1 + num2;
}
console.log(sum(10, 10));// 20

var anotherSum = sum;
console.log(anotherSum(10, 10));// 20

sum = null;
console.log(anotherSum(10, 10));// 20

上面的代碼首先定義了一個名爲sum的函數,用於求兩個數的和。而後,又聲明瞭變量anotherSum,賦值爲sum,此時anotherSumsum就指向了同一個函數,所以anotherSum()也正常返回告終果。即便切斷sum與函數對象的引用關係,也不會影響anotherSum對象

函數名做爲指針,也能夠理解爲何ECMAScript中沒有函數重載(函數名相同,參數列表不一樣)的概念。來看下面的示例:ip

function add(num){
  return 100 + num;
}
function add(num, num2){
  return 200 + num;
}
console.log(add(100));// 300

按照函數重載的概念,兩個add函數的參數列表不一樣,當傳入一個參數時應該調用第一個add,當傳入兩個參數時應該調用第二個add。但如上例所示,即便傳入一個參數依然是調用第二個add,結果爲300,這是爲何呢?

答案在函數名是指針,因此第二個add覆蓋了第一個add,也許用函數表達式的寫法更容易理解:

var add = function(num){
  return 100 + num;
};
var add = function(num, num2){
  return 200 + num;
};

如上例所示,從新聲明add會覆蓋第一個add。而JavaScript中的函數調用會根據實際傳入的參數個數按順序匹配參數列表,好比這裏傳入了一個100,那麼add中的num就爲100num2undefined,若是像這樣調用add(100, 20),那麼num2則爲20

ECMAScript 2015引入了let關鍵字能夠避免變量覆蓋的問題,以下所示:

var add = function(num){
  return 100 + num;
};
//Uncaught SyntaxError: Identifier 'add' has already been declared
let add = function(num, num2){
  return 200 + num;
};

解析的時候已經報錯,提示add已經聲明,因此使用let會更安全一些。

最近在重讀唐浩明先生的小說《曾國藩》,裏面曾國藩講到,看書要作到四點:看讀寫做。看指的就是一般的默默的閱讀,能夠增長閱讀量;讀指高聲朗誦,他講一些詩詞歌賦等文章,非高聲朗誦不能體會其中奧妙;寫是抄寫,看書時遇到經典的段落文章、好的句子,要抄寫下來,既能加深理解,又能以備往後查閱;做是根據本身的理解再創做,這是檢測本身是否真的理解以及提升做文能力的重要途徑。

本文算是抄寫吧,雖然有稍些改動,但基本和原書內容一致,記錄下來,一方面加深印象,另外一方面也是分享給讀者。

相關文章
相關標籤/搜索