什么是閉包
閉包,官方的解釋是:一個擁有需要許多變量和綁定了這=這些變量的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。閉包的特點:
1 作為一個函數變量的引用,當函數返回時,其處於激活狀態。2 一個閉包就是當一個函數返回時,一個沒有釋放資源的棧區。
簡單的說,javascript允許使用內部函數----即函數定義個函數表達式位於另一個函數的函數體內。而且,這些內部函數可以訪問它們所在的外部函數中聲明的局部變量、參數和聲明和其他內部函數。當其中一個這樣的內部函數在包含它們的外部函數之外被調用時,就會形成閉包。、
在javascript中每個函數都有一個Prototype屬性,而對象沒有。
1 不使用prototype屬性定義的對象方法,是靜態方法,只能直接用類名進行調用,另外,此靜態方法中無法使用this變量來調用對象其他的屬性。
使用prototype屬性定義的對象方法,是非靜態方法,只有在實例化之后才能使用,其方法內部可以this來引用對象自身中的其他屬性。
javascript閉包的用途
模擬面向對象的代碼風格,
1 匿名自執行函數
let arr1=[1,2,3,4]; (function(arr){ alert(arr.join(",")); })(arr1);
匿名函數,立即執行,由於外部無法引用它內部的變量,因此在函數執行完之后會立刻釋放資源,關鍵是不污染全局對象。
結果緩存 封裝
實現類和繼承
我們定義一個Person方法,就像一個類,定義方法繼承Person,並添加自己的方法
function Person(){ this.Name="zhangsan"; this.age=20; } let demo=function(){}; demo.prototype=new Person(); demo.prototype.say=function(){alert('this is a say function')} let a=new demo(); a.age //20 a.Name //‘zhangsan’ a.say();
如果一個函數訪問了它的外部變量,那么它就是一個閉包,閉包是一個函數,這個函數能夠訪問其他函數的作用域中的變量
閉包也會有很多弊端
function demo(){ var arr=[]; for(var i=0; i<10;i++){ arr[i]=function(){ console.log(i); } } } let arr=demo(); arr.map(fn=>{ fn(); });
結果打印的都是10;因為內部函數訪問外部的變量,內存中i沒有釋放;想要達到預期的效果,可以改成如下:
function demo(){ var arr=[]; for(var i=0; i<10;i++){ arr[i]=function(num){ return function(){ console.log(num); } }(i);//立即執行的匿名函數,執行完之后就釋放i的引用 } } let arr=demo(); arr.map(fn=>{ fn(); });
結果打印的是1 2 3 4 5 6 7 8 9