JavaScript中的函數

函數類型

函數其實是對象,由於每一個函數都是Function這個構造函數的實例,具備Funtion構造函數定義的屬性和方法。函數名實際上時指向函數對象的指針,說明這個問題,看以下代碼:編程

function sum(a,b) {
        return a + b;
    }
    // 至關於把sum的引用地址傳遞給sum2。
    // 注意:不帶圓括號的函數名是訪問函數指針,而非調用函數
    var sum2 = sum; 
    sum2(1,2) // 3
    sum = null;
    sum(2,3) // undefined // 將sum的內存回收,即sum的引用地址變了
    sum2(2,3) //5 // 但sum2 仍是指向原來的內存地址

1. 沒有重載

理解了上面以後,重載至關於給函數變量從新修改了引用的值,所以後面會覆蓋前面的,很容易理解了。數組

2.函數提高

其實和變量提高相似,就是聲明型函數和表達式定義函數的區別,很簡單app

3.做爲值的函數

由於函數名自己是變量,因此能夠做爲值進行傳遞,這裏有一個很好的例子,也是一個很好的編程思想,以下:函數

function getSomeFunction(fn,arg) {
    return fn(arg);
} 
function add(num) {
    return num + 10;
}
function getGreeting(name) {
    return `Hello ${name}`;
}
getSomeFunction(add,5) // 15
getSomeFunction(getGreeting,'andy') // Hello andy

還能夠從一個函數中返回另外一個函數。例如咱們在用數組的一些排序方法或者迭代方法的時候,由於傳遞進去的都是一個函數變量做爲參數,因此這個參數咱們能夠用「外部函數返回函數」的方法進行編寫,這樣作的好處是,返回的函數能夠把咱們」特定想要規定」的參數傳遞進去進行計算,例如this

// 規定利用哪一個屬性進行排序,若是不填則表明數組從大到小排序
function sortArgFuntion(compareProperty) { //compareProperty是上文中特定想要規定的參數

    return function (val1, val2) {
        if (compareProperty === undefined) {  // 若是排序的是數組的值,則用常規的方法
            if (val1 > val2) {
                return 1;
            } else if (val1 < val2) {
                return -1;
            } else {
                return 0;
            }
        } else {    // 若是排序的是對象的屬性則用該方法
            if (val1[compareProperty] > val2[compareProperty]) {
                return 1;
            } else if (val1[compareProperty] < val2[compareProperty]) {
                return -1;
            } else {
                return 0;
            }
        }

    }
}
var data = [{
    name: 'andy',
    age: 25
}, {
    name: 'Nf',
    age: 29
}]
data.sort(sortArgFuntion('name'))

sort函數的參數是個函數,用於將數組進行重排序。而咱們將這個函數參數拿出來,就能夠更直觀的、複用性更高的去編寫這個函數,達到咱們想要的效果。同時須要仔細揣摩,理解函數返回函數的精髓和獨到之處es5

4.函數內部屬性

函數內部有兩個特殊變量prototype

  • arguments
  • this

arguments

是類數組對象,何爲類數組對象呢?能夠經過序號進行數組式的訪問(如obj[1]),而且有length屬性(對象你不定義length屬性,是沒有length的).類數組只有索引值和長度,沒有數組的各類方法,因此若是要類數組調用數組的方法,就須要使用Array.prototype.method.call 來實現指針

this

this是JavaScript很是容易混淆和複雜的一個知識點,他表明什麼徹底取決於調用位置,我會但列出一篇總結this。e.g:code

window.color = 'red';
var o = {color:"blue"};
function sayColor() {
    console.log(this.color)
}
sayColor(); // red 由於調用位置是全局
o.sayColor = sayColor;
o.sayColor(); // blue 由於調用位置是o的對象裏

從上面例子中咱們要知道,函數名字僅僅是一個指針,雖然執行環境不一樣,全局的sayColor()和函數中的o.sayColor()指向的都是同一個函數對象

caller

es5新加的,他返回當前函數(必須是函數,對象不行)的調用環境,若是調用環境是全局,則返回null。有兩種用法,一種是函數名加caller,一種是arguments.callee.caller

function outer() {
        console.log(outer.caller); //null
        inner();
    };
    function inner() {
        console.log(inner.caller); // outer裏的代碼
    }

5.函數的屬性和方法

由於函數也是對象,因此也有屬性和方法;函數裏面有length和prototype兩個屬性,length指傳入形參的個數
function add(num1,num2) {} console.log(add.length) // 2

propertype(回頭好好研究一番)

對於引用類型而言,propertype是保存全部實例方法的真正所在。在建立自定義引用類型以及實現繼承,它的做用及其關鍵(到底多關鍵暫時還不太理解,尤爲是繼承這個詞:)) es5中propertype不可枚舉,所以不能遍歷。

apply() 和 call()

兩個參數,第一個參數是在哪一個做用域運行,第二個參數apply是傳入的Array或者arguments對象,call是傳入每一個值,其他他倆如出一轍。這是其中一個例子,用來講明apply和call的做用:

var color = "red";
    var o = {color:"blue"};
    function sayColor() {
        alert(this.color)
    }
    sayColor(); // red
    sayColor.call(this); // red 
    sayColor.call(window); // red
    sayColor.call(o); // blue

若是不用call的話咱們須要這樣作:

var color = "red";
    var o = {color:"blue"};
    function sayColor() {
        alert(this.color)
    }
    o.sayColor = sayColor;
    o.sayColor(); //blue

因此對比能夠一目瞭然,call一個最大的做用是實現了對象和方法的解耦

bind方法

bind方法用來構建一個函數的實例,其this對象指向bind規定的做用域。e.g:

var color = "red";
    var obj = {color:"blue"}
    function sayColor() {
        console.log(this.color);
    }
    var bindSayColor = sayColor.bind(obj);
    bindSayColor(); // blue
相關文章
相關標籤/搜索