Javascript相对于很多纯粹的面向对象和面向过程的语言有很大的区别,具备灵活性,这里我们先抛开它面向对象的特征讨论。

 

  对于大多数面向过程式的语言而言,函数就是一个有名称的代码段,方便重用。 

  例如,当我们需要大量数字求和的运算,如果在代码中大量使用加号运算符会浪费很多代码,

  于是我们可以将他们封装到一个函数体内,以后我们可以直接调用就可以使用了

function sum(a,b){
return a+b;
}
var n=sum(1,2);

 

1.函数基本概念

  (1)函数参数(arguments)——灵活的参数

function sum(){
var res= 0;
for(i=0;i<arguments.length;i++){
res
+=arguments[i];
}
return res;
}
sum(
1,2,3,4);

    在Javascript的函数中有个名为arguments的类似数组的对象。而它实际上并不是个数组,使用typeof arguments语句尝试会返回"Object"对象,所以它不能像Array一样使用push和pop等方法。即便如此,仍然可以使用下标以及长度(length)获取它的值。

代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="JavaScript">
<!--
/**
* arguments不是数组(Array类)
*/
Array.prototype.selfvalue
= 1;
function testAguments(){
alert(
"arguments.selfvalue=" + arguments.selfvalue);
}

alert(
"Array.sefvalue=" + new Array().selfvalue);//打印 "Array.sefvalue=1"

testAguments();
//打印 "arguments.selfvalue=undefined"
//
-->
</script>
</head>
<body>
</body>
</html>

 

   转化为实际的数组

var args=Array.prototype.slice.call(arguments);

  另外由于参数数不定,那么如何判断函数实际传入的参数和定义的参数

 

代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="JavaScript">
<!--
/**
* 演示arguments的用法,如何获取实参数和形数数
*/
function argTest(a,b,c,d){
var numargs = arguments.length;
// 获取被传递参数的数值。
var expargs = argTest.length;
// 获取期望参数的数值。
alert("实参数目为:"+numargs);
alert(
"形数数目为:"+expargs);
alert(arguments[
0]);
alert(argTest[
0]); //undefined 没有这种用法
}
/**
* 下面调用分别打印:
* "实参数目为:2"
* "形数数目为:4"
* "1"
* "undefined"
*/
argTest(
1,2);

/**
* 下面调用分别打印:
* "实参数目为:5"
* "形数数目为:4"
* "1"
* "undefined"
*/
argTest(
1,2,3,4,5)
//-->
</script>
</head>
<body></body>
</html>

  函数还有2个属性,一个是caller,一个是callee,分别获得该函数的引用,和形参数;

代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="JavaScript">
<!--
/**
* 演示函数的caller属性.
* 说明:(当前函数).caller:返回一个对函数的引用,该函数调用了当前函数
*/
function callerDemo() {
if (callerDemo.caller) {
var a= callerDemo.caller.arguments[0];
alert(a);
}
else {
alert(
"this is a top function");
}
}

function handleCaller() {
callerDemo();
}

callerDemo();
//打印 "this is a top function"

handleCaller(
"参数1","参数2"); //打印 "参数1"
//
-->
</script>
</head>
<body>
</body>
</html>

 

代码
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="JavaScript">
<!--
/**
* 演示函数的callee属性.
* 说明:arguments.callee:初始值就是正被执行的 Function 对象,用于匿名函数
*/
function calleeDemo() {
alert(arguments.callee);
}

calleeDemo();
// 打印 calleeDemo 整个函数体
(function(arg0,arg1){alert("形数数目为:"+arguments.callee.length)})();//打印 "形数数目为:2"
//
-->
</script>
</head>
<body>
</body>
</html>

 

 (2)作用域

    一个函数的执行,实际上是在当前作用域下,新建了一个子作用域.(注意下面的var的使用)  

function f1(){
var v1=1;
}
f1();
alert(v1);
//报错

 由下可见,在函数体子作用域内不使用var,则定义的全局变量

function f2(){   
v1
=1;
}
f2();
alert(v1);
//1

  接下来一个例子我证明该全局变量的范围。

function f3(){

function f4(){   
v1
=1;
alert(
"现在在f4中v1等于"+v1);
}
f4();
alert(
"现在在f3中v1等于"+v1);
}
f3();
alert(
"现在在window中v1等于"+v1);

 结果全部弹出,由此证明不使用var的全局变量是window的变量 

 

2.匿名函数

参考《javascript精粹》译者秦歌博客:http://dancewithnet.com/2008/05/07/javascript-anonymous-function/

 在Javascript定义一个函数一般有如下三种方式:

 

 函数关键字(function)语句:

function fnMethodName(x){

  alert(x);

}


函数字面量(Function Literals):

var fnMethodName = function(x){

  alert(x);

};

 

Function()构造函数: 

var fnMethodName = new Function('x','alert(x);');

上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。

 

 匿名函数的代码模式

  错误模式:其无法工作,浏览器会报语法错。

function(){  alert(1);}();

  1. 函数字面量:首先声明一个函数对象,然后执行它。

(function(){alert(1);})();

  2.优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数。  

(function(){alert(2);}());

 3.Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数 

void function(){alert(3);}()

 

3.内部函数(Inner Function)

 

  把函数作为一个值来思考一下,既然一个值可以定义在函数中,把函数做为数据放在函数中也未尝不可。如下:


function outer(param){
function inner(theinput){
return theinput *2;
}
return 'The result is '+inner(param);
}

也可以写成:

var outer= function(param){
var inner = function(theinput){
return theinput*2;
};
return 'The result is '+inner(param);
};

 

inner函数在outer函数之中的 ,也就是意味着,在outer函数的外部是无法访问inner函数的。所以也称之为私有函数(private function);

如果要让外部能够访问内部,则需要使用闭包。

 

 内部函数的是使用还是有很多好处的。

1.可以有更少的全局变量。过多的使用全局变量就有可能由于命名冲突而产生过多的bugs

2.私有性,可以设计更好的接口函数供外部访问