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