对于大多数面向过程式的语言而言,函数就是一个有名称的代码段,方便重用。
例如,当我们需要大量数字求和的运算,如果在代码中大量使用加号运算符会浪费很多代码,
于是我们可以将他们封装到一个函数体内,以后我们可以直接调用就可以使用了
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);}();
( 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.私有性,可以设计更好的接口函数供外部访问