嵌套函数的定义和使用

函数是可以嵌套的

function sayHelloWorld()   {
    	function add(x, y) {
            return(x + y);
    	}
    	alert(add(2, 3));
}
sayHelloWorld();            

这样当调用sayHelloWorld(); 时,将顺序执行其中的代码,内嵌函数被初始化并可以被调用。

注意内嵌函数add(),必须在位于嵌套他的函数sayHelloWorld()内调用,而不能在嵌套他的函数外调用。

而且内嵌函数也必须通过调用才能执行。

function outer(){
   alert("outer函数被调用");
   function inner() {
      return "inner函数被调用";
   }    	
   alert(inner()); // 调用inner
}
inner(); //  错误,不能在这里调用
outer(); // 正确,可以在这里调用

无名(匿名)函数(函数表达式)

1   当函数语句被定义的时候,在同一个脚本代码中被优先考虑,因此,无论该函数是在定义之前或定义之后都可以被脚本引用,例如可以这样做:

//可以不按照代码顺序调用函数
myfunc();
function myfunc() {
   //执行一些语句
}

而函数表达式只能是在创建后才能被引用,且必须按照代码编写的顺序。这不难理解,因为函数表达式只有赋给一个变量后才能被引用、例如下面的应用就是错误的:

   myfunc(); // 错误的调用
   var  myfunc = function() {
          // 执行一些语句
  }
  // 只能在这里调用myfunc()函数

闭包

首先必须理解JavaScript的变量作用域,变量的作用域包括全局变量和局部变量。

函数内部可以使用全局变量, 但是函数外却不能使用函数内的局部变量

var n = ’test’ ;
function f1() {
   alert (n);
}
 f1(); // test

 function f1(){
   var n=’test’;
}
  alert (n);  // error

有时需要得到函数内的局部变量。但是必须通过变通方法实现。即在函数内部再定义一个函数,如:

function f1(){
      var n=’test’;
      function f2(){
          alert (n);
      }
}

在上面的代码中,函数f2被包括在函数f1内部。这时f1内部的所有局部变量对f2都是可见的,但f2内部的局部变量对f1不可见。这就是JavaScript语言特有的“链式作用域”结构,子对象会一级一级向上查找所有父对象的变量。所以父对象的所有变量对子对象都是可见的,反之则不成立。

闭包的最大用处有两个,一是前面提到的读取函数内部的变量;二是让这些变量的值始终保持在内存中,实现数据共享。

var cnt = ( function () {
     var i=0;
     return function () {
         alert (i);
         i++;
     }
   } ) ();
      cnt();  // 显示0
      cnt();  //显示1
      cnt();  //显示2

           第一次调用后开始执行无名函数,执行后变量i的值将保存在内存中;第二次调用时将使用内存中保存的i值。

向闭包内部传入参数

var cnt = (function (num) {
         return  function () {
                 alert (num);
                 num++;
         }
} ) (5);
cnt();  //显示5
cnt(); //显示6
cnt(); //显示7

调用时指定参数

var cnt = (function (num) {
  return  function (num) {
      num +=1;
      alert ( num );
     num++;
  }
} ) ();
cnt(5);  //显示6
cnt(6); //显示7
cnt(7); //显示8

使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。