本文內容:javascript
今天看了javascript函數的相關知識,果真平時用多了各類框架,對於原生js的掌握並沒那麼深刻,每次看都有新的收穫,本篇文章和你們分享對於函數名和函數參數的理解,以及爲何JS中沒有函數重載的概念。html
函數名是指向函數對象的指針
首先要知道Javascript中的函數實際上也是對象,每一個函數都是Function類型的實例而已。由於是對象,因此函數名其實和包含對象指針的其餘變量沒有什麼區別,也是一個指向函數對象的指針。java
var obj = {} function a () { console.log(1) }
如上,變量obj實際上是指向一個空對象的指針,一樣函數名a與變量obj並沒什麼不一樣,也是指向此函數對象的一個指針。
**再次強調一遍,函數名僅僅是指向函數對象的指針!**
那麼下面的例子就能夠很好的理解了:數組
function a (num1, num2) { return num1 + num2 } var b = a alert(b(1,1)) // 2 a = null alert(b(1,1)) // 2
以上代碼中,首先定義了一個函數a,而後將其賦值給變量b, 由於知道了a是指向咱們所定義的函數的指針,因此這個賦值操做其實作的是將a指向的地址傳遞給變量b,此時b也指向了咱們定義的函數對象,那麼調用b就會執行咱們定義的函數,即使接下來改變了a的指向爲一個空對象,但並不影響b的指向,也就依然能正常執行函數,輸出函數結果2.過程以下:瀏覽器
理解函數參數
javascript中的函數參數與其餘語言中的函數參數有所不一樣,javascript中的參數沒有參數個數和類型的限制,也就是說,不管你定義的時候定義了幾個參數,實際調用的時候依然能夠傳任意多個參數,甚至不傳,更沒有參數類型的限制。
之因此是這樣,緣由是javascript中的在內部使用一個數組來表示的。函數內部接收到的始終是這個數組,不關心數組有哪些參數或者是否有參數。而在函數體內能夠經過arguments來訪問這個參數數組,獲取到函數的每個參數。
arguments
只是一個相似數組的對象,但它並非Array的實例。它一樣能夠經過下面這種方式訪問它的每個元素:arguments[0],arguments[1]...一樣擁有length屬性,表示函數傳遞進來的參數個數。閉包
function doSomething (num1, num2) { if (arguments.length > 2) { // 若是函數有兩個以上的參數 console.log(arguments[2]) // 輸出第三個參數 } }
arguments獲取到的函數參數與對應的函數形參的同步特性
arguments有一個特殊的性質,就是它的值永遠和對應的形參保持同步。
舉個例子就明白了,若是一個函數的參數有三個,實際調用的時候只傳了兩個參數,那麼前兩個arguments元素與形參保持同步,即共享數據而且改變時保持同步,而第三個形參與arguments[2]是不一樣步的。app
function fn (a, b, c) { console.log(a === arguments[0]) // true a = {name: 'zhangsan', age: 18} console.log(arguments[0]) // {name: 'zhangsan', age: 18} console.log(b === arguments[1]) // true arguments[1] = {name: 'lisi'} console.log(b) // {name: 'lisi'} c = 40 console.log(arguments[2]) // undefined arguments[2] = '123' console.log(c) // 40, 可見c與arguments[2]是互不影響的 } var p1 = {name: 'xiaoming', age: 6} var p2 = {age: 10} fn(p1, p2)
**注意:沒被傳遞參數的形參和相應的arguments元素都被賦值爲undefined,就像是定義了變量,但沒有被初始化同樣。**
*另外,形參與對應的arguments元素保持同步,並不表明他們是讀取相同的內存空間,它們的內存空間是獨立的,只是值會同步而已。*框架
arguments對象三個有用屬性:length、callee、properties-indexes函數
arguments.callee應用以下:性能
function fn(n) { if (n <= 1) { return 1 } else { return n * arguments.callee(n - 1) // arguments.callee指向當前函數的引用,這裏至關因而在遞歸調用fn() } } console.log(5) // 20
雖然使用arguments.callee消除了函數的執行與函數名的緊密耦合,不論函數名怎麼改變,這裏都能正確遞歸調用此函數。可是訪問arguments是一個很是昂貴的操做,由於arguments是一個很大的對象,每次遞歸時都須要從新建立。影響現代瀏覽器的性能,還會影響閉包,因此arguments.callee並不同意使用。
將arguments對象轉爲數組
有兩種方法能夠將arguments對象轉爲數組:
到這裏對函數參數和函數名作了這些瞭解後,咱們就能夠深刻理解下爲何javascript中沒有函數重載了。請看下篇文章:
[深刻理解爲何javascript沒有函數重載](http://www.javashuo.com/article/p-xdklqlig-cy.html)