所謂過程式編程(或函數式編程),最重要的語法就是函數,js雖然號稱OOP語言,但實際上函式編程是更爲經常使用且你們熟悉的編程方式。這裏就幾個重要概念進行說明。編程
總結來講,函數是js語言的第一類對象,能夠被調用、賦值、傳遞....數組
函數定義安全
function 函數名(參數1,參數2,參數3...){閉包
函數體語句app
renturn 返回值;函數式編程
}函數
說明:this
一、函數體return關鍵字指定返回值,由於是弱對象語言,所以不須要在定義中指定函數返回值,也能夠沒有return語句,返回值是undefined;spa
二、參數不用指定類型,若是類型很重要,須要使用typeof方法進行檢測。參數個數可變,且調用時個數能夠不和參數個數匹配。prototype
在函數內定義函數,叫嵌套函數。
用函數直接量定義函數,函數直接量是表達式,能夠定義匿名函數。
function f(x){ return x*x;} var f = function(x){ return x*x;}; //第一行是常規定義方式,第二行匿名函數量的方式定義函數。
雖然直接量匿名定義函數,也能夠對函數命名,這在遞歸編程中很是有用。
var f = function fact(x){ if (x<-1) return 1; else return x*fact(x-1); };
函數參數
函數能夠以任意數目的參數來調用,而無論函數定義中參數多少,向任何函數傳遞任意類型的參數都是合法的。
一、可選參數
當調用函數時,參數少於申明的參數個數的時候,其餘參數的值是undefined。所以但願編寫某些參數可選的安全的函數,方法是爲可以忽略的參數分配一個合理的默認值。但參數的順序是必須的,所以可選參數應放在最後。
function copyPropertyNamesToArray(o,/* optional */ a){ if(!a) a=[]; //若是undefined 或者 null,使用空數組 for(var property in o ) a.push(property); return a; } var a = copyPropertyNamesToArray(o); //不使用可選的參數a copyPropertyNamesToArray(p,a); //使用兩個參數
二、Arguments對象
在函數體內,能夠用arguments標示符引用auguments對象,arguments對象是一個相似數組的對象,可按照數目獲取傳遞給函數的參數值,並定義了callee屬性。
arguments.length屬性返回參數個數,arguments[0]返回第一個參數的值,使用數組下標方式獲取參數值。
屬性callee用來引用當前正在執行的函數,可用來對未命名的函數遞歸調用自身。
function(x){ if(x<=1) return 1; return x*arguments.callee(x-1); }
如何不用記住參數順序調用參數?
前面講到,調用函數參數個數雖然不限,但參數順序是必須保證的,這比較麻煩。讓參數以鍵名/值對的方式傳遞參數,是一個好辦法。實現方法是定義一個對象,用對象屬性名/值做爲函數參數。
function arrayCopy(/*array*/ from,/*index*/from_start,/*array*/ to,/*index*/to_start,/*integer*/ length) { // 方法代碼,數組from從from_start位置開始複製長度爲length的數據到到數組to從to_start位置開始,長度爲length; } function easyCopy(args){ arrayCopy(args.from, args.from_start||0, args.to, args.to_start||0, args.length); } var a=[1,2,3,4]; var b=new Array(4); easyCopy({from:a,to:b,length:4});
函數能夠做爲數據賦值給變量。
function square(x) { return x*x;} var a=square(4); //a=16 var b=square; //b引用到square var c=b(5); //c=25
函數能夠複製給對象的屬性,稱爲方法。方法其實不過是存儲在對象屬性中的而且經過對象來調用的函數,不過和一般函數不一樣的是,對象會默認給方法賦值一個對象實例,標示符是this。
var o=new Object; o.square=function(x){ return x*x;} y=o.square(16);
還能夠複製給數組元素。
var a=new Array(3); a[0]=function(x){ return x*x; } a[1]=20; a[2]=a[0](a[1]); //a[2]=400
函數還能夠做爲參數傳遞給其餘函數。
函數的屬性和方法
函數是js對象的一種特殊類型,也具備屬性和方法。
length屬性:只讀屬性,返回參數個數;
prototype屬性:預約義的原型對象;
函數自定義屬性:能夠在函數內部定義變量做爲函數的屬性;
apply()和call()方法:該方法能夠像調用其餘對象的方法同樣調用函數。第一個參數是要調用的函數的值,在函數體內這個參數是關鍵字this,剩餘參數是要傳遞給要調用的函數的值。
f.call(o,1,2); 等同於: o.m=f; o.m(1,2); delete o.m;
函數做用域和閉包
調用對象
當js解釋器調用一個函數,它首先將做用域設置爲定義函數的時候起做用的那個做用域鏈。接下來,在做用域鏈前面添加一個新的對象,叫作調用對象。調用對象用arguments屬性調用函數的Arguments對象,函數的命名的參數和var語句的局部變量添加到調用對象的後面。
閉包
子函數可使用父函數中的局部變量,這種行爲就叫作閉包!按照js做用域鏈原理,嵌入函數老是可以訪問外部函數的全部參數和變量。所以,全部函數都是閉包的,嵌入函數可做爲閉包使用。