嵌套函数的定义和使用
函数是可以嵌套的
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),这时一定要小心,不要随便改变父函数内部变量的值。