所在的位置: js >> js资源 >> js中对函数的深入理解上

js中对函数的深入理解上

北京中科白癜风医院好不好 http://hunan.ifeng.com/a/20170705/5797804_0.shtml
在js中,对函数的定义首先是使用function关键字来声明,后跟方法名和一组参数以及函数体,其基本的语法格式如下:functionfunctionName(arg0,arg1,……argn){需要执行的函数体}调用这个函数只需要在该函数后面执行functionName(参数1,参数2,……,参数n);就可以了,如果需要函数返回值;则需要使用return关键字,如:functionadd(x,y){returnx+y;}我们调用函数:varnum=add(2,6);打印console.log(num)值为8;这里return关键字还有另一个用法,就是结束函数的执行;比如:functionadd(x,y){returnx+y;alert()}这里我们调用add函数将得到x+y的返回值,而return后面的语句将不会执行。我们也可以单独使用return关键字而不返回值,这样函数就不再往下执行,此时函数返回一个undefind,在函数中,return语句一般我们用于函数的返回值或者在函数体分支语句中停止函数的执行。在严格模式下,函数名和参数名都不能为eval和arguments,且不能出现两个同名参数的情况。我们在调用函数的时候,有时候函数只定义了两个参数,但我们可以给它传递一个或多个参数值,此时代码也可以正常运行。其实在函数中,有一个类似数组的对象arguments,它并非Array的实例;但它有着和数组类似的使用方法,可以使用arguments[0],arguments[1]和argments.length来查看传递参数的值和参数个数,如:functionadd(x,y){console.log(arguments[0]);console.log(arguments[1]);console.log(arguments.length);}add(12,你好)此时函数将会打印12,你好和2,这里其实我们在函数定义的时候也可以不用写参数名,定义参数名只是为了便利,但不是必须的;functiontest(){console.log(arguments.length)}test();//打印0test(,12);//打印2test(你好);//打印1这并不算其他语言中意义上的方法重载,在js中,没有重载概念这一说,如果说在同一作用域中定义了两个同名函数,那么后面的将覆盖前面的函数;而且,在严格模式下对arguments做了一些限制:functiondosay(arg1,arg2){arguments[1]=Hello;console.log(arg2)}报错:严格模式(strictmode)下执行将会报:UncaughtSyntaxError:Unexpectedidentifier错误。我们这里所定义的每一个函数,其实都是Function类的实例,函数名实际上是一个指向函数的指针,与其他引用类型一样有自己的属性和方法,除了以上我们定义函数的方式之外还可以使用变量的方式来定义:varfunName=function(arg1,arg2){returnarg1+arg2;}其实和上面的定义方式几乎差不多;只是使用函数表达式的方式定义的函数不能申明提前,也就是说在定义该函数之前不能调用该函数:函数申明方式:test(你好);//正常调用functiontest(str){console.log(str)}函数表达式方式:dosay(x,y);//报错dosayisnotafunctionvardosay=function(x,y){returnx+y;}解析器会先读取函数申明,并让其在执行任何代码之前可以调用该函数。而表达式方式申明的函数,必须要等到解析器执行到它所在的代码,才可以真正的被调用。所以上面的例子中调用add函数会报错,就是因为函数表达式申明的函数不会申明提前。最后一种函数的定义方式是使用Function构造函数;如:varfun1=newFunction(arg1,arg2,returnarg1+arg2);在这里我们不推荐使用这种方式来创建函数,所以不对它进行详解。之前我们说到,函数名只是一个指向函数的指针,并且我们可以使用变量的方式来创建一个函数,那么我们可不可以把这个函数名当作参数传递给另一个函数呢?答案是肯定的,函数名本身就是变量。我们来看看这个例子:functiontest(x,y,add){returnadd(x,y);}varadd=function(arg1,arg2){returnarg1+arg2;}console.log(test(,,add));//打印并且我们还可以从一个函数返回另一个函数,这也是一种极为常用的技术,比如:functiontest1(address){returnfunction(name,age){return我叫+name+;今年+age+岁了;我来自+address;};}varperson=test1(贵阳);varp1=person(Tom,25);console.log(p1);//我叫Tom;今年25岁了;我来自贵阳在函数内部,有两个特殊的对象arguments和this,arguments对象我们之前介绍过,这个对象还有一个属性callee,该属性是一个指针,指向arguments对象所在的函数。我们来看两个经典的递归案例:functionaddNum(count){if(count=1){return1;}else{returncount*addNum(count-1);}}这里我们只考虑参数为数值的情况,在上面代码中,我们的递归函数addNum与函数名耦合在了一起,而如果我一旦修改函数名的话,函数内部也要修改,为了消除这种耦合。我们可以使用arguments.callee;functionaddNum(count){if(count=1){return1;}else{returncount*arguments.callee(count-1);}}在这个递归函数体内,就没有在引用函数名addNum了,这样不管以后我们怎么修改函数名,也不影响函数正常执行了。


转载请注明:http://www.aierlanlan.com/rzgz/8717.html