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