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
posted @ 2018-11-15 21:00  陈皮KirinaChen  阅读(2442)  评论(0编辑  收藏  举报