js函數、作用域、作用域鏈、閉包、立即執行函數


1.函數

定義

1.函數聲明

function test(){
函數體
};

2.函數表達式:
- 命名函數表達式 
- ```java
var fn = function test(){};
  • (匿名)函數表達式

var fn = function(){};


#### 組成形式
1.函數名稱
2.參數(形參、實參)
3.返回值

### 2.作用域
1. 作用域定義:變量(變量作用域又稱上下文)和函數生效的區域。
2. [[scope]]:每個js函數都是一個對象,對象中的屬性有些我們可以訪問,有些不可以,這些屬性僅供js引擎存取,[[scope]]就是其中一個,[[scope]]存取了運行期上下文的集合。
3. 作用域鏈:[[scope]]中鎖存儲的執行期上下文對象的集合,這個集合呈鏈式鏈接,我們把這種鏈式鏈接成為作用域鏈。
4. 執行期上下文:當函數執行時,會創建一個執行期上下文的內部對象。一個執行期上下文定義了一個函數執行時的環境,函數每次執行時對應的執行器上下文都是獨一無二的,所以多次調用函數就會創建多個執行器上下文,當函數執行完畢,它所產生的執行期上下文會被銷毀。
5. 查找變量:從作用域鏈頂端向下查找。

### 3.閉包
1. 定義:當內部函數被保存到外部時,將會生成閉包。閉包將會導致作用域鏈不釋放內存,導致內存泄露。
```java
function a(){
	function b(){
		
	}
	return b;//保存到外部
}
var demo = a();
demo();
demo();
//a()執行的時候,會定義b,b是在a執行的時候定義,定義的時候會在aAO -- > GO,並且a執行后返回b,b被保存到外部,故這個之后aAO不會被釋放,從而造成內存泄露。
  1. 閉包的作用
  • 實現公有變量
    • 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. 立即執行函數
針對初始化功能的函數
立即執行函數執行完就被銷毀。
```java
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM