欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript 函數(shù)使用說(shuō)明

 更新時(shí)間:2010年04月07日 13:10:16   作者:  
其實(shí)通俗的說(shuō)就是一個(gè)有名稱的代碼段,方便重用。

什么是函數(shù)(Function)
function sum(a,b){ 
     return a+b; 

其實(shí)通俗的說(shuō)就是一個(gè)有名稱的代碼段,方便重用。
要注意的是:
1.Javascript 的函數(shù)語(yǔ)法,因?yàn)镴avascript本身就是區(qū)分大小寫的,所以function不能寫作Function或FUNCTION.
2.sum是函數(shù)的名稱,這個(gè)并不是必須的,等以后我們會(huì)說(shuō)到。
3.return是返回,如果不寫的話,函數(shù)的返回是undefined.如果要返回多個(gè)值,可以返回個(gè)數(shù)組或者對(duì)象(以后再說(shuō))
函數(shù)的調(diào)用

下面我們講函數(shù)的基本調(diào)用。

var result = sum(1,2) 
函數(shù)的參數(shù)

不好意思的說(shuō),這個(gè)才是本篇文章的重點(diǎn)。
實(shí)例一,參數(shù)少于 實(shí)際定義參數(shù)的數(shù)目
var result = sum(1); 
結(jié)果result 為NaN,這就說(shuō)明了,參數(shù)b的值為undefined,但并不會(huì)報(bào)錯(cuò),這就無(wú)形中制造了bug.
實(shí)例二,參數(shù)多于 實(shí)際定義參數(shù)的數(shù)目
sum(1,2,3,4,5) 
結(jié)果為3.發(fā)現(xiàn)多于的參數(shù)被忽略了。
實(shí)例三,沒(méi)有參數(shù)的函數(shù)
function args(){return arguments;} 
每個(gè)函數(shù)里都有一個(gè)默認(rèn)的數(shù)組那就是arguments .它就是每個(gè)函數(shù)默認(rèn)的參數(shù)為[] 。如果我們調(diào)用函數(shù)如下
args(1,2,3,4,5,6); 
會(huì)發(fā)現(xiàn)arguments的值為[1,2,3,4,5,6]。這下容易了,我們可以改造下上面的sum方法

function sum(){ 
    var res= 0; 
    for(i=0;i<arguments.length;i++){ 
        res+=arguments[i]; 
    } 
    return res; 

sum(1,2,3,4); 
結(jié)果為10,這個(gè)sum函數(shù)靈活多了吧。^_^

Functions are data

這一篇是函數(shù)里比較重要的概念,那就是函數(shù)是一個(gè)數(shù)據(jù)??磦€(gè)例子
function f(){return 1;} 
var f=function(){return 1;} 
這兩個(gè)函數(shù)定義都是相同的。
typeof f; 
f的值為"function",所以說(shuō)Javascript 的 函數(shù)是個(gè)數(shù)據(jù)類型。它有比較兩個(gè)重要的特點(diǎn)
1.它包含了代碼
2.能被執(zhí)行
看個(gè)例子
var sum = function(a,b){return a+b;} 
var add = sum; 
sum=undefined; 
typeof sum; 
typeof add; 
add(1,2); 
我們把函數(shù)sum做為一個(gè)值賦給了add,發(fā)現(xiàn)刪除了sum不影響add的調(diào)用。所以函數(shù)也就是個(gè)正常的賦值。
匿名函數(shù)(Anonymous Functions)
Javascript中,可以不用寫賦值的代碼,如
"abcd" 1 [1,2,3] 
這樣都不會(huì)報(bào)錯(cuò),這些數(shù)據(jù)叫做匿名的。同樣的函數(shù)做為數(shù)據(jù)也可以是匿名的
function(a){return a} 
匿名函數(shù)的作用有兩個(gè)
1.可以把匿名函數(shù)做為一個(gè)參數(shù)傳入到另一個(gè)函數(shù)中。
2.你可以理解運(yùn)行這個(gè)匿名函數(shù)
下面就會(huì)詳細(xì)討論這兩個(gè)功能的作用了。

回調(diào)函數(shù)(Callback Functions)

因?yàn)楹瘮?shù)和其他數(shù)據(jù)一樣可以被賦值,刪除,拷貝等,所以也可以把函數(shù)作為參數(shù)傳入到另一個(gè)函數(shù)中。
實(shí)例一
function invoke_and_add(a,b){ 
  return a()+b(); 

function one(){ 
  return 1; 

function two(){ 
  return 2; 

invoke_and_add(one ,two); 
結(jié)果為3;
再來(lái)看看匿名函數(shù)的用法。
實(shí)例二
invoke_and_add(function(){return 1;},function(){return 2;}),直接一個(gè)函數(shù)體傳進(jìn)去,沒(méi)有函數(shù)名。
我們稱,invoke_and_add為回調(diào)函數(shù) 
我們用匿名函數(shù)替代了 one,two兩個(gè)函數(shù)。
通過(guò)上面兩個(gè)實(shí)例,回調(diào)函數(shù)的定義為:傳遞一個(gè)函數(shù)A到另一個(gè)函數(shù)B中,并且這個(gè)函數(shù)B執(zhí)行函數(shù)A。我們就說(shuō)函數(shù)A叫做回調(diào)函數(shù)。 說(shuō)白了,就是被人直接調(diào)用的函數(shù),在一個(gè)函數(shù)執(zhí)行另一個(gè)函數(shù)!
如果沒(méi)有名稱,就叫做匿名回調(diào)函數(shù)

回調(diào)函數(shù)的作用

主要有三個(gè)
1.當(dāng)函數(shù)作為參數(shù)傳遞的時(shí)候,不用為這個(gè)函數(shù)定義一個(gè)名稱,這樣的好處是減少了全局變量。
2.節(jié)省了大量的代碼。
3.提高了程序的性能。

自調(diào)用函數(shù)(Self-invoking Functions)

自調(diào)用函數(shù)也是匿名函數(shù)的一種表現(xiàn)形式,這個(gè)函數(shù)在定義之后,直接調(diào)用。如下

function(){ 
   alert('haha'); 

)() 

看起來(lái)還挺怪異,不過(guò)確實(shí)很簡(jiǎn)單。
自調(diào)用函數(shù)很方便使用,可以不用定義更多的全局變量。還有個(gè)好處,就是這個(gè)函數(shù)不能被執(zhí)行兩遍。真是非常適合做初始化的工作。
許多著名的javascript庫(kù)特別多的源碼中使用了這個(gè)功能,例如本人喜歡的Jquery.

內(nèi)部函數(shù)(Inner Functions)

把函數(shù)作為一個(gè)值來(lái)思考一下,既然一個(gè)值可以定義在函數(shù)中,把函數(shù)做為數(shù)據(jù)放在函數(shù)中也未嘗不可。如下:
function a(param){ 
function b(theinput){        
   return theinput *2; 

return 'The result is '+b(param); 

也可以這么寫
var a = function(param){ 
     var b = function(theinput){ 
        return theinput*2; 
     }; 
     return 'The result is '+b(param); 
}; 
b函數(shù)是在a函數(shù)之中的 ,也就是意味著,在a函數(shù)的外部是無(wú)法訪問(wèn)b函數(shù)的。所以也稱之為私有函數(shù)(private function)
a(2); 
a(8); 
b(2); 
發(fā)現(xiàn)b(2)是沒(méi)有定義的。也就確定了它確實(shí)是私有函數(shù)。
內(nèi)部函數(shù)的是使用還是有很多好處的。
1.可以有更少的全局變量。過(guò)多的使用全局變量就有可能由于命名沖突而產(chǎn)生過(guò)多的bugs
2.私有性,可以設(shè)計(jì)更好的接口函數(shù)供外部訪問(wèn)。

返回值為函數(shù)的函數(shù)(Functions that Return Functions)

在前幾篇文章已經(jīng)介紹了函數(shù)要有返回值,即使沒(méi)有寫return,函數(shù)也會(huì)返回一個(gè)undefine。
接下來(lái)看看返回值為函數(shù)的情況
function a(){ 
alert('a'); 
return function(){ 
  alert('b'); 
}; 

在這個(gè)例子中,a函數(shù)執(zhí)行了alert('a'),以及它返回了另一個(gè)函數(shù)b。關(guān)于返回b的調(diào)用我們可以這樣來(lái)用。
var newFunc = a(); 
newFunc(); 
執(zhí)行結(jié)果為 alert a和alert b
如果不想賦值調(diào)用這個(gè)函數(shù)也可以簡(jiǎn)寫如下
a()(); 
函數(shù)的自身重寫

因?yàn)楹瘮?shù)可以返回一個(gè)函數(shù),那就意味著可以用一個(gè)新的函數(shù)替代一個(gè)舊的函數(shù),根據(jù)前一個(gè)例子來(lái)改進(jìn)一下
a=a(); 
第一次運(yùn)行函數(shù)a,就alert a,再次運(yùn)行函數(shù)a,就alert b,這個(gè)功能對(duì)初始化非常有用。這個(gè)函數(shù)a重寫了自己,避免在以后調(diào)用初始化的功能(上個(gè)例子為alert a)。
當(dāng)然我們還有更簡(jiǎn)單的方法來(lái)重寫a函數(shù)那就是在a函數(shù)的內(nèi)部重寫它,來(lái)看看代碼
function a(){ 
alert("a") 
a=function(){ 
   alert("b"); 


只有在初次調(diào)用a函數(shù)才會(huì)執(zhí)行 alert a 在以后的調(diào)用中,都會(huì)執(zhí)行alert b
下面結(jié)合前幾節(jié)看個(gè)綜合的例子
var c = function(){ 
   function a(){ 
    alert('a') 
   } 
   function b(){ 
    alert('b') 
   } 
   a(); 
   return b; 
}();//alert('a'); 
c();//alert('b'); 
這個(gè)例子有以下幾點(diǎn)需要注意
1. a函數(shù),b函數(shù)是內(nèi)部函數(shù)。
2. return b 返回的是個(gè)函數(shù)的引用。
3. 子調(diào)用函數(shù)重寫了函數(shù)c。

如果能明白這個(gè)例子,關(guān)于內(nèi)部函數(shù),子調(diào)用函數(shù)和返回值為函數(shù)的函數(shù)就可以都理解了。

閉包(Closures)閉包屬于比較難的一部分,在學(xué)習(xí)閉包之前,先來(lái)學(xué)習(xí)以下Javascript的作用域(Scope)

作用域鏈(Scope Chain)

函數(shù)內(nèi)部定義的變量,在函數(shù)外不能訪問(wèn),或者變量定義在代碼段中(如if,for中),在代碼段之外也不可訪問(wèn)。
var a =1; 
function f(){ 
var b=1; 
return a; 

f();//a=1 
b;//b 沒(méi)有定義 
a 是全局變量,而b定義在函數(shù)f之中。所以:
在f函數(shù)中,a和b都可以訪問(wèn)。
在f函數(shù)之外,a可以訪問(wèn),而b不可以

再次看個(gè)例子
var a = 1; 
function f(){ 
var b = 1; 
function n(){ 
  var c =3; 


如果定義一個(gè)函數(shù)n在函數(shù)f中,函數(shù)n不但可以訪問(wèn)自己作用域的c,而且還能訪問(wèn)所謂的父作用域的b和a
這就是作用域鏈(Scope Chain)
詞法作用域(Lexical Scope)

在Javascript中,也有詞法作用域(Lexical Scope),這個(gè)意思是,函數(shù)在定義的時(shí)候就生成了它的作用域,而不是在調(diào)用的時(shí)候,看個(gè)例子就明白了。
function f1(){var a=1;f2();} 
function f2(){return a;} 
f1();//a沒(méi)有定義 
先看看函數(shù)f1,調(diào)用了函數(shù)f2,因?yàn)楹瘮?shù)局部變量a也在f1中,可能期望函數(shù)f2也訪問(wèn)a,但事實(shí)卻不是這樣。
因?yàn)檫@個(gè)時(shí)候f2函數(shù)已經(jīng)定義完畢了,而它的范圍沒(méi)有a被找到。不管是函數(shù)f1還是函數(shù)f2,僅僅能訪問(wèn)的是本身的局部變 量或者全局變量。

用閉包來(lái)破壞這個(gè)作用域鏈(Breaking the Chain with Closure)

讓我們舉例來(lái)說(shuō)明閉包吧。
實(shí)例1

function f(){ 
var b="b"; 
return function(){ 
  return b; 


函數(shù)f包含了變量b,在全局作用域中不可能訪問(wèn)b,結(jié)果為沒(méi)有定義(undefined)。
看看這個(gè)函數(shù)的返回值為一個(gè)函數(shù)。這個(gè)新的函數(shù)可以訪問(wèn)f范圍中的變量b??慈缦麓a
var n = f(); 
n();//訪問(wèn)b 
由于函數(shù)f本身就是全局的,而它返回的函數(shù)又是個(gè)新的全局函數(shù),而它又可以訪問(wèn)函數(shù)f的作用域。

實(shí)例2
這個(gè)例子和上個(gè)例子結(jié)果是一樣的,但是有一點(diǎn)不同,函數(shù)f并不返回一個(gè)函數(shù),而是新建一個(gè)全局變量n,代碼如下
var n; 
function f(){ 
var b = "b"; 
n=function(){ 
  return b; 


所以可以直接n()來(lái)訪問(wèn)函數(shù)f里的變量b

通過(guò)上面兩個(gè)例子我們就可以說(shuō)當(dāng)一個(gè)函數(shù)指向了它的父作用域,其作用是指向局部變量,就可以稱之為閉包。
閉包其實(shí)就提供了一個(gè)借口,一個(gè)讓外部訪問(wèn)內(nèi)部的變量的方法

當(dāng)我們創(chuàng)建了個(gè)傳遞參數(shù)的函數(shù)f,這個(gè)參數(shù)就變成了函數(shù)f的局部變量了。我們可以創(chuàng)建一個(gè)f的內(nèi)部函數(shù)來(lái)返回這個(gè)參數(shù)
function f(arg){ 
var n =function(){ 
   return args; 

  arg++; 
return n; 

var m= f(123); 
m();//124 

閉包在循環(huán)中的應(yīng)用

再循環(huán)中很容易引起一些bug,雖然表面是正常的。
看如下的代碼
function f(){ 
    var a = []; 
    var i; 
    for(i=0;i<3;i++){ 
        a[i] = function(){ 
            alert(i); 
            return i; 
        } 
    } 
    return a; 

var a= f(); 
a[0]();//3 
a[1]();//3 
a[2]();//3 
新建個(gè)循環(huán),我們的目的是每次循環(huán)都新建一個(gè)函數(shù),函數(shù)返回的是循環(huán)的序列值也就是i。我們看看以上代碼的運(yùn)行結(jié)果
都是為3.而我們期望的結(jié)果是1,2,3。
到底是為什么呢?我們新建了三個(gè)閉包,都指向了變量i。閉包并沒(méi)有記住變量i的值,它僅是變量i的引用。在循環(huán)結(jié)束后,i的值是3,所以結(jié)果都是3了。

來(lái)看看正確的寫法
function f() { 
  var a = []; 
  var i; 
  for(i = 0; i < 3; i++) { 
    a[i] = (function(x){ 
      return function(){ 
        alert(x); 
        return x; 
      } 
    })(i); 
  } 
  return a; 

var a = f(); 
a[0]();//0 
a[1]();//1 
a[2]();//2 
我們又用了一個(gè)閉包,把變量i變成了局部變量x了,x變量每次都是不同的值了。如果沒(méi)有徹底理解自調(diào)用函數(shù)那就如下寫法就可以明白了
function f() { 
  function makeClosure(x) { 
    return function(){ 
      return x; 
    } 
  } 
  var a = []; 
  var i; 
  for(i = 0; i < 3; i++) { 
    a[i] = makeClosure(i);  //makeClosure,用來(lái)記憶i的值。
  } 
  return a; 

相關(guān)文章

最新評(píng)論