javascript--浅谈函数与闭包

一、函数

  函数对于任何一种语言来说都是一个核心的概念。通过函数封装多条语句,并可以在任何地方,任何时候调用,ECMAScript中规定,函数使用function关键字声明,后面跟一组参数以及函数体。

 

函数声明的基本方式主要是以下三种,比较常用第1、2种

//方式1
function fn1(arg0, arg1,....){
    alert("这是一个函数");
}
fn1();//调用

//方式2
var fn2 = function(arg0, arg1,...){
    "这是一个函数"
}
fn2();

//方式3
var fn3= new Function('alert('这是一个函数')');
fn3();

javascript与其他语言不相同的是,在function声明中,参数并不需要指定参数的类型。ECMAScript中没有函数签名的概念,因为起函数参数是以一个包含零个或者 多个值的数组的形式传递的,使用者可以向函数传递多个参数,并且可以通过arguments对象来访问这些参数。也是由于没有函数签名,所以function函数不能重载,但是可以通过arguments对象模拟重载。

  在开发过程中,我们会常常在一个函数体内定义另一个函数体,并将其作为一个返回值返回。这个也就是所谓的闭包。

 

二、闭包

  闭包就是指有权访问另一个函数作用域中的变量的函数。常见的创建闭包的方式就是在一个函数内部创建另一个函数。

以下面代码为例:

function myFunction(name){
    return function(name){
                alert("你传入的名字为"+name);
     }
}

var fn = myFunction(name);
fn("jiangZ");

 myFunction()函数内部返回了另外一个函数,将其作为一个变量返回,并在fn的定义中,赋给了函数fn,就相当于fn()的函数就是:fn(name){alert("你传入的名字为"+name);} 

那么使用闭包的好处就在于不产生全局变量,属性私有化。但是外部的函数可以通过这种方式调用到另外一个函数的内部变量。这就涉及到一个作用域链的问题了。

function fn(){
var value1 = 1;
var value2 = 2;
return function(){

if(value1 > value2){alert(value1);}
else{alert(value2);}
};
}
var f = fn();
f();

value1、value2是函数fn内部的私有属性,但是外部函数 f 可以访问到这两个属性。之所以可以是因为内部函数的作用域链中包含了fn()函数的作用域。当一个函数被调用时,就会创建一个执行环境以及相应的作用域链,然后使用arguments和其他命名参数的值来初始化函数的活动对象,但是在作用域链中外部函数的活动对象始终是处于第二位,外部函数的外部函数的活动对象处于第三位,以此类推,直到作为作用域链终点的执行环境。在一个函数(fn)内部定义的函数会将包含函数(即外部函数 f)的活动对象中添加到他的作用域中。也就是说fn 内部function的执行环境中实际上会包含value1和value2。所以当fn的内部函数被返回后,其作用域链被初始化为包含了fn函数的的活动对象跟全局变量。这样外部的函数就可以访问在fn中的所有变量。一般来说。局部活动对象会在执行环境结束后被销毁,但是闭包不同,就算函数执行完毕后,起活动对象仍然会存留在内存中。因为外部的函数的作用域链汉时引用着这个活动对象。直到函数被销毁后,fn的活动对象才会被销毁。所以对于使用闭包的缺点就是闭包中的数据会常驻内存,在不用的时候要删掉否则会导致内存溢出。

 

posted @ 2017-09-28 14:38  _江江江江  阅读(208)  评论(0编辑  收藏  举报