javascript函數篇1、理解javascript中的函數參數(arguments對象相關問題)和函數名

本文內容:javascript

  • 理解函數是對象,函數名是指針;
  • 理解函數的參數問題 ===> arguments對象相關

今天看了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函數

  1. length:真正傳遞的參數個數;
  2. callee:指向當前函數的引用(caller:調用當前函數的函數,二者不一樣之後會有介紹);
  3. 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對象轉爲數組:

  1. Array.prototype.slice.apply(arguments);
  2. Array.from(arguments); 

 

到這裏對函數參數和函數名作了這些瞭解後,咱們就能夠深刻理解下爲何javascript中沒有函數重載了。請看下篇文章:
[深刻理解爲何javascript沒有函數重載](http://www.javashuo.com/article/p-xdklqlig-cy.html)

相關文章
相關標籤/搜索