js函式、作用域、作用域鏈、閉包、立即執行函式
阿新 • • 發佈:2018-11-15
1.函式
定義
1.函式宣告
- ```java
function test(){
函式體
};
2.函式表示式:
- 命名函式表示式
- ```java
var fn = function test(){};
- (匿名)函式表示式
var fn = function(){};
組成形式
1.函式名稱
2.引數(形參、實參)
3.返回值
2.作用域
- 作用域定義:變數(變數作用域又稱上下文)和函式生效的區域。
- [[scope]]:每個js函式都是一個物件,物件中的屬性有些我們可以訪問,有些不可以,這些屬性僅供js引擎存取,[[scope]]就是其中一個,[[scope]]存取了執行期上下文的集合。
- 作用域鏈:[[scope]]中鎖儲存的執行期上下文物件的集合,這個集合呈鏈式連結,我們把這種鏈式連結成為作用域鏈。
- 執行期上下文:當函式執行時,會建立一個執行期上下文的內部物件。一個執行期上下文定義了一個函式執行時的環境,函式每次執行時對應的執行器上下文都是獨一無二的,所以多次呼叫函式就會建立多個執行器上下文,當函式執行完畢,它所產生的執行期上下文會被銷燬。
- 查詢變數:從作用域鏈頂端向下查詢。
3.閉包
- 定義:當內部函式被儲存到外部時,將會生成閉包。閉包將會導致作用域鏈不釋放記憶體,導致記憶體洩露。
function a(){ function b(){ } return b;//儲存到外部 } var demo = a(); demo(); demo(); //a()執行的時候,會定義b,b是在a執行的時候定義,定義的時候會在aAO -- > GO,並且a執行後返回b,b被儲存到外部,故這個之後aAO不會被釋放,從而造成記憶體洩露。
- 閉包的作用
- 實現公有變數
- eg: 函式累加器
function add(){ var count = 0; function demo(){ count++; console.log(count); } return demo; } var counter = add(); counter(); counter(); counter();
- 可以做快取(儲存結構)
多個函式被儲存為一個函式的閉包,它們操作的是同一塊記憶體。- eg:eater
function test(){ var num = 100; function a(){ num++; console.log(num); } function b(){ num--; console.log(num); } return [a,b]; } var myArr = test(); myArr[0]();//101 myArr[1]();//100
function eater(){ var food = "apple"; var obj = { eatFood: function () { if(food != ""){ console.log("eating " + food); food = ''; }else{ console.log("it is empty.") } }, pushFood: function (myfood) { food = myfood; } } return obj; } var person = eater(); person.eatFood();//eating apple person.pushFood("banana"); person.eatFood();//eating banana
- 可以實現封裝,屬性私有化
- eg:Person()
- 模組化開發,防止汙染全域性變數
4. 立即執行函式
針對初始化功能的函式
立即執行函式執行完就被銷燬。
var num = (function (a,b,c){
var d = a+b+c;
return d;
}(1,2,3));
PS:只有表示式才能被執行符號執行。
var test = function(){};
test();//表示式,可以被執行。
+ function (){
console.log('a');
}();//可以執行,前面加的+讓它變成了表示式。加-也一樣的道理。
function test(){
var arr = [];
for(var i = 0;i <10;i++){
arr[i] = function(){
document.write(i+" ");
}
}
return arr;
}
var myarr = test();
for(var j = 0;j < 10;+j+){
myarr[j]();
}//10 10 10 10 10 10 10 10 10 10
//arr裡面存的十個元素都是函式體,返回arr後被儲存到外部,形成閉包,當myarr = test()執行的時候,arr裡面存了十個函式體,最後退出test的時候i=10.當執行myarr[j]的時候,運用的是test()的執行期上下文,而test()退出時,testAO裡面的i=10.故輸出了10個10.
function test(){
var arr = [];
for(var i = 0;i <10;i++){
(function (j){
arr[j] = function() {
document.write(j+" ");
}
}(i));
}
return arr;
}
var myarr = test();
for(var j = 0;j < 10;j++){
myarr[j]();
}//0 1 2 3 4 5 6 7 8 9