JavaScript紅寶書筆記(七)---Function類型

1.函數其實是對象。每一個函數都是 Function 類型的實例,並且都與其餘引用類型同樣具備屬性和方法數組

2.因爲函數名僅僅是指向函數的指針,所以函數名與包含對象指針的其餘變量沒有什麼不一樣app

function sum(num1, num2){
    return num1 + num2;
}
alert(sum(10,10)); //20
var anotherSum = sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20

3.ECMAScript中函數沒有重載函數

4.函數聲明和函數表達式的區別:解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用(能夠訪問);至於函數表達式,則必須等到解析器執行到它所在的代碼行,纔會真正被解釋執行this

alert(sum(10,10));
function sum(num1, num2){
    return num1 + num2;
}                              //函數聲明提高,正常執行

alert(sum(10,10));
var sum = function(num1, num2){
    return num1 + num2;
};                            //報錯

5.做爲值得函數:不只能夠像傳遞參數同樣把一個函數傳遞給另外一個函數,並且能夠將一個函數做爲另外一個函數的結果返回;僅使用函數名能夠訪問函數的指針而不執行函數。prototype

function add10(num){
    return num + 10;
}
var result1 = callSomeFunction(add10, 10);
alert(result1); //20

6.函數內部屬性arguments指針

arguments它是一個類數組對象,包含着傳入函數中的全部參數,它還包含一個屬性交callee,該屬性是一個指針,指向擁有這個 arguments 對象的函數。callee屬性能夠用來解耦合。code

function factorial(num){
if (num <=1) {
    return 1;
} else {
    return num * factorial(num-1)        //利用factorial函數名回調遞歸
    }
}

這樣作法若是以後factorial賦值給別的變量,而後又從新賦值一個函數給factorial。那麼別的變量並不會調用到本來的遞歸函數,而是調用到factorial新賦值的函數。因此須要消除這種緊耦合。對象

function factorial(num){
    if (num <=1) {
        return 1;
    } else {
        return num * arguments.callee(num-1)
    }
}

var trueFactorial = factorial;

factorial = function(){
    return 0;
};

alert(trueFactorial(5)); //120
alert(factorial(5)); //0

7.函數內部屬性this
this引用的是函數據以執行的環境對象——或者也能夠說是 this 值繼承

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

ps:函數的名字僅僅是一個包含指針的變量而已。所以,即便是在不一樣的環境中執行,全局的sayColor()函數與o.sayColor()函數指向的仍然是同一個函數。遞歸

8.函數都包含的屬性與length和protoType。
length是函數接收的命名參數個數;
protoType是保存他們全部實例方法的真正所在,例如valueOf(),toString(),只不過是經過各自對象的實例訪問。另外,prototype 屬性是不可枚舉的,所以使用 for-in 沒法發現。

9.每一個函數都包含兩個非繼承而來的方法:apply()和 call()。這兩個方法的用途都是在特定的做用域中調用函數
apply()方法接收兩個參數:一個是在其中運行函數的做用域,另外一個是參數數組

function sum(num1, num2){
    return num1 + num2;
}
function callSum1(num1, num2){
    return sum.apply(this, arguments); // 傳入 arguments 對象
}
function callSum2(num1, num2){
    return sum.apply(this, [num1, num2]); // 傳入數組
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20

call()方法與 apply()方法的做用相同,它們的區別僅在於接收參數的方式不一樣。傳遞給函數的參數必須逐個列舉出來。

function sum(num1, num2){
    return num1 + num2;
}
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20

10.傳遞參數並不是 apply()和 call()真正的用武之地;它們真正強大的地方是可以擴充函數賴以運行的做用域

window.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()(或 apply())來擴充做用域的最大好處,就是對象不須要與方法有任何耦合關係。

相關文章
相關標籤/搜索