高程3總結#第7章函數表達式

函數表達式

遞歸

  • 遞歸函數是在一個函數經過名字調用自身的狀況下構成的javascript

    function factrial(num){
      if(num<=1){
        return 1;
      }else {
        return num*factrial(num-1);
      }
    }
  • argument.callee是一個指向正在執行的函數的指針,所以能夠用它來實現對函數的遞歸調用java

    function factorial(num){
      if(num<=1){
        return 1;
      }else {
        return num*argument.callee(num-1)
      }
    }
  • 嚴格模式下不能經過腳本訪問argument.callee,訪問這個屬性會致使錯誤,不過可使用命名函數表達式類達成相同的結果閉包

    var factorial=(function f(num){
      if(num<=1){
        return 1;
      }else {
        return num*f(num-1);
      }
    })

閉包

  • 閉包是指有權訪問另外一個函數做用域中的變量的函數app

    function compare(value1,value2){
      if(value1<value2){
        return -1;
      }else if(value1>value2){
        return 1;
      }else {
        return 0;
      }
    }
    var result=compare(5,10)

    圖片描述

    //建立函數
    var compareNames = createComparisonFunction("name");
    //調用函數
    var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
    //解除對匿名函數的引用(以便釋放內存)
    compareNames = null;

    圖片描述

閉包與變量

  • 閉包只能取得包含函數中任何變量的最後一個值,i值爲10函數

    function creatFunctions(){
      var result=new Array();
      for(var i=0;i<10;i++){
        result[i]=function(){
          return i;
        };
      };
      return result;
    }
  • 經過匿名函數強制讓閉包的行爲符合預期this

    function createFuntion(){
      var result=new Array();
      for(var i=0;i<10;i++){
        result[i]=function(num){
          return function(){
            return num;
          };
        }(i);
      }
      return result;
    }

關於this對象

  • 匿名函數的執行環境具備全局性,所以其this對象一般指向window
  • 把外部做用域中的this對象保存在一個閉包可以訪問到的變量裏,就能夠了讓閉包訪問這個對象了spa

    var name="The Window";
    var object={
      name:"My Object",
      getNameFunc:function(){
        var that=this;
        return function(){
          return that.name
        };
      }
    };
    alert(object.getNameFunc()());//"My Object"
  • 定義米明函數以前,咱們把this對象賦值給了一個名叫that的變量,而在定義了這個閉包以後,閉包也能夠訪問這個變量,所以它是咱們在包含函數中特地聲明的一個變量,即便在函數返回以後,that也仍然引用這object

內存泄漏

  • 若是閉包做用域中保存着一個HTML元素,那麼久意味着該元素將沒法被銷燬prototype

    function assignHandler(){
      var element=docunemt.getElementById("someElement");
      element.onclick=function(){
        alert(element.id)
      }
    }
  • 以上代碼段中的element佔用的內存永遠不會被回收指針

    function assignHandler(){
      var element=document.getElementById("someElement");
      var id=element.id;
      element.onclick=function(){
        alert(id);
      }
      element=null;
    }

模仿塊級做用域

function outputNumbers(count){
  for(var i=0;i<count;i++){
    alert(i);
  }
  var i;//從新聲明變量
  alert(i);//計數
}
  • JavaScript歷來不會告訴你是否屢次聲明瞭同一個變量,遇到這種狀況,只會對後續的聲明視而不見,不過會執行後續聲明中的變量初始化。匿名函數能夠用來模仿塊級做用域來避免這個問題code

    (function(){
      //這裏是塊級做用域
    })()
  • 代碼定義並當即調用了一個匿名函數,將函數聲明包含在一對圓括號中,表示它其實是一個函數表達式,而緊隨其後的另外一對圓括號會當即調用這個函數。

    function outputNumbers(count){
      (function(){
        for(var i=0;i<count;i++){
          alert(i)
        }
      })();
      alert(i);//致使一個錯誤
    }
  • 這種技術常常在全局做用域中被用在函數外部,從而限制向全局做用域中添加過多的變量和函數。通常來講,咱們應該儘可能少向全局做用域中添加變量和函數

私有變量

  • JavaScript中滅有私有成員的概念,因此對象屬性都是共有的。任何在函數中定義的變量,均可以認爲是私有變量,由於不能在函數的外部訪問這些變量,私有變量包括函數的參數、局部變量和在函數內部定義的其餘函數。
  • 若是在函數內部建立一個閉包,那麼閉包經過本身的做用域鏈也能夠訪問函數內的變量

靜態私有變量

(funciton(){
  //私有變量和私有函數
  var privateVariable=10;
  function privateFunction(){
    return false;
  }
  //構造函數
  MyObject=function(){}
  //公有/特權方法
  MyObject.prototype.publicMethod=function(){
    privateVariable++;
    return privateFunciton();
  }
})();
  • 在私有做用域中,首先定義了私有變量和私有函數,而後又定義了構造函數及其公有方法

模塊模式

  • 模塊模式是爲單例建立私有變量和特權方法。單例指的就是隻有一個實例的對象。按照慣例,JavaScript是以字面量的方式來建立單例對象的

    var singleton={
      name:value,
      method:function(){
        //這裏是代碼方法
      }
    }
  • 模塊模式經過爲單例添加私有變量和特權的方法可以使其獲得加強

    var singleton=function(){
      //私有變量和私有函數
      var privateVariable=10;
      funciton privateFunction(){
        return false;
      }
      //特權/公有方法和屬性
      return {
        publicProperty:true,
        publicMethod:function(){
          privateVariable++;
          return privateFunction();
        }
      };
    }();

加強的模塊模式

var application = function(){
//私有變量和函數
var components = new Array();
//初始化
components.push(new BaseComponent());
//建立 application 的一個局部副本
var app = new BaseComponent();
//公共接口
app.getComponentCount = function(){
  return components.length;
};
app.registerComponent = function(component){
  if (typeof component == "object"){
    components.push(component);
  }
};
//返回這個副本/
return app;
}();
相關文章
相關標籤/搜索