javasript 中的函数表达式(两种):
一 函数声明
function functionName(arg0,arg1,...){
//函数体
}
关于函数声明有一个重要的特征就是函数声明提升(理解),即在执行代码之前会读取函数声明,意味着可以在函数声明前调用函数
二 创建函数表达式
函数表达式有几种不同的表达方式这里介绍最常见的一种
匿名函数(拉达姆函数)function关键字后面没有标识符其name属性是空
var functionName = function(){
//函数体
}
理解函数表达式与函数声明的关键在于理解函数声明提升
// 错误
if(条件){
function sayHi(){//函数体1}
}else{
function sayHi(){/函数体2}
}
//正确
var sayHi;
if(条件){
sayHi = function(){//函数体1}
}else{
sayHi = function(//函数体2){}
}
函数的递归:
if(num<=1){
return 1;
}else{
return factorial(num-1)*num;
}
}
这是一个计算阶乘的函数表面没什么问题实际在有的时候会出错
var anotherFunction=factorial;
factorial=null;
alert(anotherFunction(4))//出错! 此代码在执行anotherFunction的时候必须先执行factorail,应用argument.callee就能解决问题argument.callee是一个指向正在执行函数的指针
function factorial(num){
if(num<=1){
return 1;
}else{
return arguments.callee(num-1)*num;
}
}
但是argument.callee在严格环境中是不能访问此属性的,所以我们可以用命名函数表达式来代替,这样就能两全其美了!
function factorial=(function f(){
if(num<=1){
return 1;
}else{
return arguments.callee(num-1)*num;
}
});
闭包:
function f1(){
n=999;
function f2(){
alert(n); // 999
}
}
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),
子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
function f1(){n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
f2函数,就是闭包。 “闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
}
return innerFun; //注意这里
}
var obj=outerFun();
obj(); //结果为1
obj(); //结果为2
var obj2=outerFun();
obj2(); //结果为1
obj2(); //结果为2
如上代码还可以理解为:
当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.
模仿块级作用域:
在 javascript中可以利用匿名函数来模仿块级作用域语法如下:
(function(){
//这里是块级作用域
})();
//无论在什么时候需要临时变量,就可以使用私有作用域
function OutPutNumber(count){
(function(){
for(int i=0;i<count;i++){
alert(i);
}();
})
}
私有变量:
在javascript中严格来讲是没有私有成员的概念的,任何在函数里定义的变量都可以认为是私有变量
而静态私有变量是在私有作用域中定义的变量
关于私有变量牵扯到javascript的一种常见的编码模式----模块模式,会有一个讲模块模式的专题
萨达