在javascript中,function作为一个关键字有两方面的应用。
     a、可以定义函数。
     b、可以定义一个数据类型。这里只介绍函数。关于function定义类的功能在对象中介绍。
1、函数的概念
    javascript中提供了许多预定义函数,我们可以直接使用,比如Math.sin();eval()等。
我们也可以定义自己的函数。有以下四种方法:

a、function add(x,y){return x+y;}
b、var add = function(x,y){return x+y;}
c、var add = new Function("x","y","return x+y;");
d、var add =function a(x,y){return x+y;}

在这,如果用add(2,3);调用,返回的结果都是5。但它们使用有很大的区别,后面在详细解释。

2、函数的参数
     回想上一篇提到函数的调用对象。虽然我们不能访问它,看不见,但引入这个概念确实可以方便我们解释很多东西。
     在一个函数体内,标识符arguments有特殊含义。它是调用对象的一个特殊属性。

< SCRIPT LANGUAGE = " JavaScript " >
function  add(x,y) {
document.writeln('x
= ' + x);
document.writeln('y
= ' + y);
document.writeln('arguments[
0 ] = ' + arguments[ 0 ]);
document.writeln('arguments[
1 ] = ' + arguments[ 1 ]);
arguments[
0 ] = 11 ;
document.writeln('arguments[
0 ] = ' + arguments[ 0 ]);
return  x + y;
}

document.writeln(add(
2 , 3 ));
</ SCRIPT >

     看例子,基本你可以把arguments当成个数组使用,但并不是真正的数组。
    虽然arguments.length and arguments[index]可以在函数内改变,但建议你不要在函数内改变它们。关于arguments的具体用法可以看prototype.js.
arguments还有个属性 callee.引用当前正在执行的函数。

 

< SCRIPT LANGUAGE = " JavaScript " >
function  add(x,y) {
    document.writeln(arguments.callee);
    document.writeln(
typeof (arguments.callee));
    
return  x + y;
}

document.writeln(add);
document.writeln(
typeof (add));
document.writeln('
</ br >-----------------------</ br > ');
add();
</ SCRIPT >

3、函数是一种数据类型
    在javascript中,函数不但能象java一样当成语言的语法特性,还可以象字符串、数字、日期一样当成一种数据。
    var add=function(x,y){return x+y;};其实我们函数的定义都是把函数附值给变量。函数不但可以附值给变量,还可以当成参数传递。

 

< SCRIPT LANGUAGE = " JavaScript " >
var  add = function (x,y) { return  x + y;} ;
var  fun = add;
function  opetate(fun,x,y) {
    
return  fun(x,y);
}

alert(opetate(fun,
2 , 3 ));
</ SCRIPT >

 

其实javascript的熟手不会在全局变量里(直接在js文件中)定义函数,都会定义在全局变量的属性字段中。如

 

< SCRIPT LANGUAGE = " JavaScript " >
  
var  MyLib = {} ;
  MyLib.fun1
= function () {} ;
  MyLib.fun2
= function () {} ;
  alert(MyLib);
  alert(MyLib.fun1);
</ SCRIPT >

如果这种写法,我们就基本不会和别人写的程序发生命名上的冲突了。

4、函数的生命周期
    在变量里我们知道函数有个预编译过程,这个过程我们也看到不到,另外函数定义不同写法情况也不同。所以,感觉函数的执行过程很是复杂。

 

< SCRIPT LANGUAGE = " JavaScript " >
  fun1();
  alert(fun1);
// ///////////把以下代码放到定义最后面可以执行。
  fun2();
  alert(fun2)
  fun3();
  alert(fun3)
  
// /////////////////////////
   function  fun1() {document.writeln('fun1 run ! ')}
  
var  fun2  = function () {document.writeln('fun2 run ! ')} ;
  
var  fun3  = new  Function( " document.writeln('fun3 run!') " );
</ SCRIPT >


a、javascript预编译过程(在html中, </head>前后,<body>内外有特殊情况,这指纯.js文件中)
    javascript的预编译我认为是个很简单的过程,对于解释执行语言,肯定不会编译成什么中间语言。(我认为)过程如下:
    首先,为执行环境(一个html也,框架环境下有几个执行环境)建立建立一个全局对象,一般客户端脚本为 window或global对象。(在这我觉得global好理解,因为浏览器会放入window总其他的属性)
    然后,检查某环境中根代码块中(非函数或{}中)var关键字,把这些变量设置成global对象的属性,并附初值undefined.
   如果过程中遇到直接定义的函数(fun1的定义),那么把fun1设置成global对象的属性,并附初值函数的定义(你可以把函数当成undefined,true,1,'1'等数据类型)。
b、解释执行过程
   代码按照顺序执行,
   一般我们把全局变量的俯值放到代码最前面,如var s="hello";  那么把s的值用 'hello'替换预编译过程的undefined。
   如果遇到变量的应用,如代码  document.writeln(a),如果我们在global找到属性a,看a是否在前面代码俯值过,如果没有,a的值为预编译的undefined。如果是隐式变量声明,在这把它添加到global的属性中去。
   如果遇到类似var fun=function(){}; 把函数当成数据赋值给变量fun.
c、函数的调用过程
   你运行一下以下代码,为什么结果是 test undefined local

< SCRIPT LANGUAGE = " JavaScript " >
var  s = " golbe " ;
function  fun(s) {
    document.writeln(s);
    document.writeln(a);
    
var  s = " local " ;
    
var  a = "" ;
    
return  s;
}

document.writeln(fun(
" test " ));
</ SCRIPT >

 

首先:预编译代码,把s、fun设置为golbe的属性,并赋值s=undefined,fun=函数定义(可以直接调用)。
然后:按照顺序解释执行代码。赋值s="golbe";   函数已经可以直接调用了。
执行函数:当运行到fun("test")时,开始函数调用。
       先为本次调用建立一个调用对象(fun-global)。
       预编译函数体内代码,把参数设置为fun-global的属性,值为为传入值"test",查找var,把a设置成fun-global的属性,值为undefined.(如果var s与参数名称相同,则不重复设置例如函数体内var s="local";)
      按照顺序执行函数内代码,当代码中遇到变量,先从调用对象属性中查找,如果找到直接使用。遇到var s="local";时,代码会覆盖调用对象中属性值(和参数名称相同)

调用对象是个暂时对象,生命周期很短,只有在调用过程中存在,递归可能会建立多个独立的调用对象。
javascript的函数应该和java中一样是线程安全的吧。
 

5、函数的属性和方法
a、length
看了以下代码一目了然,函数的length代表函数实际需要的参数个数。

< SCRIPT LANGUAGE = " JavaScript " >
function  add(x,y) {
    
var  actual = arguments.length;
    
var  expected = arguments.callee.length;
    
if (actual != expected) {
        
throw   new  Error('函数需要' + expected + '个参数,你输入了' + actual + '个');
    }

    
return  x + y;
}

alert(add(
3 , 2 ));
alert(add(
3 , 2 , 3 ));
</ SCRIPT >

b、prototype
这个属性引用的是预定义的原型对象,只有在new 函数名 才有效。讲解对象时介绍。
c、定义自己的函数属性

< SCRIPT LANGUAGE = " JavaScript " >
add.count
= 0 ;
function  add(x,y) {
    add.count
++ ;
    
return  x + y;
}

add(
3 , 2 );
add(
3 , 2 );
add(
3 , 2 );
add(
3 , 2 );
document.writeln('共调用函数几次:'
+ add.count);
</ SCRIPT >


d、apply() call()方法
去读读prototype.js吧。