javascript 函數表達和閉包

函數表達式和閉包

針對JS高級程序設計這本書,主要是理解概念,大部分要點源自書內。寫這個主要是當個筆記加總結
存在的問題請你們多多指正!javascript

定義函數的兩種方法

函數聲明:java

function functionName(arg0,arg1,arg2){
  //函數體
}

函數表達式:閉包

var  functionName = function(arg0, arg1, arg2){
  //函數體
}

函數聲明提高:函數能夠先用,聲明在下面自動給提到上面來函數

函數表達式=後面的是匿名函數,又叫拉姆達函數,他通常能夠被用來當成值使用(能夠用來return)設計

遞歸

函數本身調用本身就叫遞歸,沒啥好說的。當函數賦值給另外一個函數時會致使從新調用函數名稱不一樣而調用失敗code

var anotherFactorial = factorial //factorial是一個遞歸函數
factorial = null 
alert(anotherfactorial(5))//error

因此在函數內部本身調用本身的時候不要使用本身的函數名,應該用耦合度更大的arguments.callee來表示本身的函數名,例如對象

fucntion factorial(num){
  if(num <= 1){
    return 1
  } else {
    //此處arguments.callee代替函數名factorial
    return num * arguments.callee(num-1)
  } 
}

閉包

總結來講就是指有權限訪問另外一個函數做用域中的變量的函數遞歸

常見的方式就是在一個函數內部建立另外一個函數。ip

先看一波閉包的效果:內存

//creatComparisonFunction是下面要說的外層函數
var compareNames = creatComparisonFunction('name')
//compareNames在調用的就是閉包函數方法了,爲何對象可以使用方法,由於閉包返回的是一個方法
var result = compareNames({ name: 'laotie' },{ name: '6666'})

仔細的說的話在一個函數裏的return出來的匿名函數就叫閉包。在做用域鏈中一個函數內部的函數能夠訪問他鏈後面(鏈後面指當前活動對象的外層,也就是內層函數外層的函數)對象的參數,然而當外面函數執行完了,裏面的函數就不能再去調用外層函數的數據了,這是由於當一個函數執行完畢時,局部活動的對象就會被銷燬,當外層函數執行完后里不只內層函數被銷燬,順帶着外層函數的數據也被銷燬了。然而經過閉包能夠實現一種效果,外層函數執行完了之後,內層函數再次調用的話還能夠調用外層函數的屬性。

由於太抽象了,因此書中給了一個例子:

//createComparisonFunction 就是一個外層函數,他傳進來一個propertyName的參數
function createComparisonFunction(propertyName){
  
  return function(object1,object2){
    //這時候內層調用了外層的參數,理論上不用閉包也行的,可是閉包的目的是當外層函數執行完了,還能夠有機會去執行內層函數並使用外層函數的參數
    var value1 = object1[propertyName]
    var value2 = object2[propertyName]
    
    if(value1 < value2){
      return -1
    } else if (value1 > value2){
      return 1
    } else {
      return 0
    }
  }
}

上面例子中return 的function就是閉包函數,閉包實現'外層函數執行完了之後,內層函數再次調用的話還能夠調用外層函數的屬性的'這種效果主要是由於匿名函數的做用域鏈中包含他的外層函數,由於匿名函數的做用域鏈始終引用着他外層函數的活動對象,因此除非接觸匿名函數的引用,不然外層函數的活動對象會一直存在。這也引發來閉包會比較佔內存,因此要慎重使用。

//跟上第一個例子:解除對匿名函數的引用
compareNames = null
相關文章
相關標籤/搜索