犀牛書學習筆記(3):函數

所謂過程式編程(或函數式編程),最重要的語法就是函數,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做用域鏈原理,嵌入函數老是可以訪問外部函數的全部參數和變量。所以,全部函數都是閉包的,嵌入函數可做爲閉包使用。

相關文章
相關標籤/搜索