第3章 函数
3.1 什么是函数
函数:本质是一种代码的分组形式。函数的声明如下:
1 <script type="text/javascript"> 2 /*函数的声明组成:function关键字、函数名称如sum、参数、 3 函数体(执行的代码块)、return子句*/ 4 function sum(a,b){ 5 return a+b; 6 } 7 </script>
3.1.1 调用函数
调用函数的方式:在函数名后面加一对用以传递参数的括号。如调用如上sum()函数。
> var result=sum(1,3);
> result;
4
3.1.2 参数
调用时忘记传递参数值,将自动设置为undefined,如
> sum(1);//1于undefined相加 NaN
参数分为形参与实参。形参:sum(a,b);实参:sum(1,3)。
可以通过arguments变量访问函数的参数。通过arguments变量完善sum()函数,对任意数量的参数执行求和运算。代码如下:
1 // arguments.length返回参数的数量 2 function sum1(){ 3 var res=0; 4 for (var i = 0; i < arguments.length; i++) { 5 res+=arguments[i]; 6 }; 7 return res; 8 }
3.2 预定义函数
内建函数:parseInt()、parseFloat()、isNaN()、isFinite()、eval()等。
3.3 变量的作用域
JavaScript以函数作为作用域,不是以代码块作为作用域。
1 <script type="text/javascript"> 2 //在函数内可以访问个local 3 //在函数外local不存在 4 var global=1; 5 function f(){ 6 var local=2;//声明变量没用使用var语句,该变量就会默认为全局变量 7 global++; 8 return global; 9 } 10 f();// 2 11 f();// 3 12 local;// local is not defined 13 </script>
变量提升
1 <script type="text/javascript"> 2 //函数域优先于全局域,局部变量a会覆盖和它同名的全局变量 3 //被提升的只有函数的声明 4 var a=123; 5 function f(){ 6 alert(a);//undefined 7 var a=1; 8 alert(a);// 1 9 } 10 /* 11 等价于: 12 var a=123; 13 function f(){ 14 var a; 15 alert(a);//undefined 16 a=1; 17 alert(a);// 1 18 } 19 */ 20 f(); 21 </script>
3.4 函数也是数据
函数也是数据,可以把一个函数赋值给一个变量。
函数表达式
<script type="text/javascript"> //函数标识记法 函数表达式 var f=function (){ return 1; }; //函数声明 function f1(){ return 1; } </script>
函数作为数据的特点:
1>包含的是代码 2>可执行的
var sum=function(a,b){return a+b}; var add=sum; typeof add; //"fucntion" add(1,2); // 3
3.4.1 匿名函数
<script type="text/javascript"> var f=function (a){ return a; }
</script>
用法:1>作为参数传递给其它函数 2>执行某些一次性任务
3.4.2 回调函数
如果将函数A传递给函数B,并由B来执行函数A,A就成为一个回调函数.
1 <script type="text/javascript"> 2 // 如果将函数A传递给函数B,并由B来执行函数A,A就成为一个回调函数 3 function add(a,b){ 4 return a()+b(); 5 } 6 function one(){ 7 return 1; 8 } 9 function two(){ 10 return 2; 11 } 12 add(one,two);// 3 13 //可是使用匿名函数(函数表达式),作为目标函数的参数 14 add( 15 function(){return 1;}, 16 function(){return 2;} 17 ); // 3 18 </script>
回调函数的优势:
1>在不做命名的情况下传递函数(节省变量名的使用)
2>将一个函数的调用操作委托给另一个函数(节省代码的编写工作)
3>有助于提升性能
3.4.3 回调示例
先将函数的三个参数分别乘以2,在加1。代码如下:
1 <script> 2 //编写一个函数,将其所有的参数乘以2 3 // function multipleByTwo(a,b,c){ 4 // var i,ar=[]; 5 // for (var i = 0; i < 3; i++) { 6 // ar[i]=arguments[i]*2; 7 // } 8 // return ar; 9 // } 10 //函数的参数加1 11 function addOne(a){ 12 return a+1; 13 } 14 // 如果要实现三个元素在两个函数之间传递,先分别乘以2在加上1 15 // 1.可以定义一个数组,来存储第一步的结果 16 /* 17 var myarr=[]; 18 myarr=multipleByTwo(21,33,2); 19 for (var i = 0; i < 3; i++) { 20 myarr[i]=addOne(myarr[i]); 21 }; 22 myarr; 23 */ 24 // 2.使用回调函数 25 function multipleByTwo(a,b,c,callback){ 26 var i,ar=[]; 27 for (var i = 0; i < 3; i++) { 28 ar[i]=callback(arguments[i]*2); 29 }; 30 return ar; 31 } 32 // multipleByTwo(1,2,3,addOne); //[3, 5, 7] 33 34 // 可以使用匿名函数来代替addOne(),节省全局变量 35 multipleByTwo(1,2,3,function(a){ 36 return a+1; 37 }); //[3, 5, 7] 38 </script>
3.4.4 即时函数
函数在定义后立即调用。
1 <script type="text/javascript"> 2 //第二个函数起着立即调用的作用 3 ( 4 function (){ 5 alert('a'); 6 } 7 )(); 8 //或者第一对括号闭合在第二对之后 9 (function(){ 10 alert('a'); 11 } 12 ()); 13 //可以在第二个括号中传递参数 14 ( 15 function (name){ 16 alert('hello '+name+' !'); 17 } 18 )('dude'); 19 </script>
3.4.5 内部(私有)函数
在一个函数内部定义另一个函数。
1 <script type="text/javascript"> 2 function outer(param){ 3 function inner(a){ 4 return a*2; 5 }; 6 return 'The result is '+inner(param); 7 }; 8 outer(2);// "The result is 4" 9 inner(2);// inner is not defined 10 </script>
使用私有函数的好处:
有助于确保全局名字空间的纯净性
确保私有性—只将一些必要的函数暴露出去
3.4.6 返回函数的函数
1 <script type="text/javascript"> 2 function f1(){ 3 alert('a'); 4 return function (){ 5 alert('b'); 6 }; 7 } 8 f1()();// 先执行 alert('a');再执行 alert('b'); 9 </script>
3.4.7 能重写自己的函数
1 <script type="text/javascript"> 2 function a(){ 3 alert('sa'); 4 a=function (){ 5 alert('qq'); 6 }; 7 } 8 a() //第一次调a时是sa 9 a() //第二次调a时是qq 10 </script>
3.5 闭包
3.5.1 作用域链
1 <script type="text/javascript"> 2 var a=1; 3 function f(){ 4 var b=2; 5 return a; 6 }; 7 f();// 1 在函数内部a、b都是可见的 8 b;// b is not defined 在函数外部a是可见的、b则不可见。 9 </script>
3.5.1 利用闭包突破作用域链
3.5.1.1 闭包#1
1 <script type="text/javascript"> 2 //返回函数形式的闭包 3 var a='glocal variable'; 4 var F=function(){ 5 var b='local variable'; 6 var N=function (){ 7 var c='inner variable'; 8 return b; 9 } 10 return N; 11 }; 12 b; // b is not defined b在全局函数中不可见 13 F();/*返回:function (){ 14 var c='inner variable'; 15 return b; 16 }*/ 17 F()(); // 返回"local variable" 通过返回函数的闭包使b在全局空间中可见 18 </script>
3.5.1.2 闭包#2
1 <script type="text/javascript"> 2 //通过全局函数的占位符,使使局部空间和全局空间连通,实现闭包 3 var inner; 4 var F=function (){ 5 var b="local variable"; 6 var N=function(){ 7 return b; 8 }; 9 inner=N; 10 }; 11 F(); //undefined 12 inner();//"local variable" 13 14 //如果只执行inner(); 15 inner(); // inner is not a function 16 </script>
3.5.1.3 闭包#3
1 <script type="text/javascript"> 2 //以参数形式形成闭包、 3 function F(param){ 4 var N=function(){ 5 return param; 6 } 7 param++; 8 return N; 9 } 10 var inner=F(111); 11 inner(); //112 12 </script>