(1)定义函数,JavaScript通常有三种定义函数方法:
*第一种是使用function语句定义函数(静态方法) javascript
1 function 函数名(var1,var2,...,varX) 2 { 3 4 代码...(return) 5 6 }
第二种是使用Function()构造函数来定义函数(不经常使用)
html
1 var 函数名 = new Function(“参数1”,”参数2”,”参数3”……”函数体”); 2 如: 3 var 函数名 = new Function(”x”,”y”,”var z=x+y;return z;”);
*第三种是在表达式中定义函数
java
1 var 函数名 = function(参数1,参数2,…){函数体}; 2 //例如: 3 //定义 4 var add = function(a,b){ 5 return a+b; 6 } 7 //调用函数 8 document.write(add(50,20));
(2)函数做用域:浏览器
函数外面定义的变量是全局变量,在整个HTML页面内都有效(生存期在整个HTML页面)。,函数内能够直接使用。在函数内部没有使用var定义的,变量则为全局变量,*在函数内使用var关键字定义的变量是局部变量,即出了函数外边没法获取。js函数定义的参数没有默认值。(目前只有最新的火狐浏览器支持)
闭包
(3)如何调用函数:函数
//sayHi函数 function sayHi(sName, sMessage) { alert("Hello " + sName + sMessage); } //调用上面的函数 sayHi(),会生成一个警告窗口 sayHi("David", " Nice to meet you!")
(4)函数如何返回值:spa
函数 sayHi() 未返回值,即便函数确实有值,也没必要明确地声明它。该函数只须要使用 return 运算符后跟要返回的值便可。设计
1 function sum(iNum1, iNum2) { 2 3 return iNum1 + iNum2; 4 5 } 6 7 //下面的代码把 sum 函数返回的值赋予一个变量: 8 9 var iResult = sum(1,1); 10 11 alert(iResult); //输出 "2"
另外一个重要概念是,与在 Java 中同样,函数在执行过 return 语句后当即中止代码。所以,return 语句后的代码都不会被执行。调试
1 function sum(iNum1, iNum2) { 2 3 return iNum1 + iNum2; 4 //alert 窗口就不会显示出来 5 alert(iNum1 + iNum2); 6 7 }
一个函数中能够有多个 return 语句,以下所示:code
1 function diff(iNum1, iNum2) { 2 3 if (iNum1 > iNum2) { 4 5 return iNum1 - iNum2; 6 7 } else { 8 9 return iNum2 - iNum1; 10 11 } 12 13 }
上面的函数用于返回两个数的差。要实现这一点,必须用较大的数减去较小的数,所以用 if 语句决定执行哪一个 return 语句。
若是函数无返回值,那么能够调用没有参数的 return 运算符,随时退出函数。
1 function sayHi(sMessage) { 2 if (sMessage == "bye") { 3 4 return; 5 6 } 7 8 alert(sMessage); 9 10 } 11 //这段代码中,若是 sMessage 等于 "bye",就永远不显示警告框 12 13 //注释:若是函数无明确的返回值,或调用了没有参数的 return 语句,那么它真正返回的值是 undefined。
在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
例如,在函数 sayHi() 中,第一个参数是 message。用 arguments[0] 也能够访问这个值,即第一个参数的值(第一个参数位于位置 0,第二个参数位于位置 1,依此类推)。
所以,无需明确命名参数,就能够重写函数:
1 function sayHi() { 2 if (arguments[0] == "bye") { 3 return; 4 } 5 alert(arguments[0]); 6 }
还能够用 arguments 对象检测函数的参数个数,引用属性 arguments.length 便可。下面的代码将输出每次调用函数使用的参数个数:
1 function howManyArgs() { 2 3 alert(arguments.length); 4 5 } 6 7 howManyArgs("string", 45); 8 howManyArgs(); 9 howManyArgs(12); 10 11 //上面这段代码将依次显示 "2"、"0" 和 "1"。 12 //与其余程序设计语言不一样,ECMAScript 不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数均可以接受任意个数的参数(根据 Netscape 的文档,最多可接受 25 个),而不会引起任何错误。任何遗漏的参数都会以 undefined 传递给函数,多余的函数将忽略。
用 arguments 对象判断传递给函数的参数个数,便可模拟函数重载:
1 function doAdd() { 2 3 if(arguments.length == 1) { 4 5 alert(arguments[0] + 5); 6 7 } else if(arguments.length == 2) { 8 9 alert(arguments[0] + arguments[1]); 10 11 } 12 } 13 doAdd(10); //输出 "15" 14 15 doAdd(40, 20); //输出 "60" 16 17 //当只有一个参数时,doAdd() 函数给参数加 5。若是有两个参数,则会把两个参数相加,返回它们的和。因此,doAdd(10) 输出的是 "15",而 doAdd(40, 20) 输出的是 "60"。虽然不如重载那么好,不过已足以避开 ECMAScript 的这种限制。
1. Function对象的使用
函数其实是功能完整的对象。Function 类能够表示开发者定义的任何函数。用 Function 类直接建立函数的语法以下:var function_name = new function(arg1, arg2, ..., argN, function_body)。
1 <html> 2 3 <head> 4 5 <script type="text/javascript"> 6 7 var sayHi = new Function("sName", "sMessage", "alert(\"Hello \" + sName + sMessage);"); 8 9 </script> 10 11 </head> 12 13 14 <body> 15 16 <script type="text/javascript" > 17 18 sayHi("Jackie","Welcome here!");//调用函数 19 20 </script> 21 22 </body> 23 24 </html>
尽管能够使用 Function 构造函数建立函数,但最好不要使用它,由于用它定义函数比用传统方式要慢得多。不过,全部函数都应看做 Function 类的实例。
2. 使用Function类的length属性
1 <html> 2 3 <head> 4 5 <script type="text/javascript"> 6 7 function fun1(){} 8 9 function fun2(a1,a2){} 10 11 function fun3(a1,a2,a3,a4,a5,a6,a7){} 12 13 </script> 14 15 </head> 16 17 18 <body> 19 20 <script type="text/javascript"> 21 22 document.write(fun1.length+" "+fun2.length+" "+fun3.length); 23 24 </script> 25 26 </body> 27 28 </html>
使用Function的length属性能够获得函数的形参个数。
3. 使用Function类的valueOf()方法和toString()方法。这两个方法返回的都是函数的源代码,在调试时尤为有用。
1 <html> 2 3 <head> 4 5 function fun() { 6 7 alert("Hi"); 8 9 } 10 11 </head> 12 13 <body> 14 15 <script type="text/javascript"> 16 17 document.write(fun.toString());//输出函数的源代码 18 19 </script> 20 21 </body> 22 23 </html>
ECMAScript 最易让人误解的一点是,它支持闭包(closure)。闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数能够使用函数以外定义的变量。
1.简单的闭包实例
在 ECMAScript 中使用全局变量是一个简单的闭包实例。请思考下面这段代码:
1 var sMessage = "hello world"; 2 3 function sayHelloWorld() { 4 5 alert(sMessage);//使用函数以外定义的变量 6 7 } 8 9 sayHelloWorld();
在上面这段代码中,脚本被载入内存后,并无为函数 sayHelloWorld() 计算变量 sMessage 的值。该函数捕获 sMessage 的值只是为了之后的使用,也就是说,解释程序知道在调用该函数时要检查 sMessage 的值。sMessage 将在函数调用 sayHelloWorld() 时(最后一行)被赋值,显示消息 "hello world"。
2.复杂的闭包实例
在一个函数中定义另外一个会使闭包变得更加复杂。例如:
1 var iBaseNum = 10; 2 3 function addNum(iNum1, iNum2) { 4 5 function doAdd() { 6 7 return iNum1 + iNum2 + iBaseNum; 8 9 } 10 11 return doAdd(); 12 13 }
这里,函数 addNum() 包括函数 doAdd() (闭包)。内部函数是一个闭包,由于它将获取外部函数的参数 iNum1 和 iNum2 以及全局变量 iBaseNum 的值。 addNum() 的最后一步调用了 doAdd(),把两个参数和全局变量相加,并返回它们的和。
这里要掌握的重要概念是,doAdd() 函数根本不接受参数,它使用的值是从执行环境中获取的。能够看到,闭包是 ECMAScript 中很是强大多用的一部分,可用于执行复杂的计算。
提示:就像使用任何高级函数同样,使用闭包要当心,由于它们可能会变得很是复杂。