文章目录
函数函数的定义局部变量外部变量内外变量重名参数参数默认值年长代码的默认参数空值合并运算符的应用返回值return陷阱小技巧函数
在编程过程中,我们经常需要在很多地方使用一段相同的代码。例如,用户的注册、登录、注销和退出代码段,经常在不同的网页页面上存在。
在每次用到这些功能时都重新写一遍代码无疑是笨拙的,这种时候我们就可以使用函数。
函数可以将一段代码封装成一个代码块,并为这段代码起个名字(函数名),每当需要使用这段代码时,只需要提供函数名称就可以了。
函数一旦写成,就可以被无限次调用,而不需要重复的写代码。
实际上,我们在之前的每节课程都在使用函数,例如:alert()
、prompt()
、confirm()
等。
这些函数都是JavaScript
为了我们方便使用自带的函数,我们也可以创建自己的函数。
在很多情况下,我们会把函数称作“方法”,函数和方法通常都是混用的,二者本质上没有什么分别。
函数的定义
函数定义需要使用一个新的关键字function
,函数定义的语法规则如下:
function funcName(para1,para2,para3,...){//函数体}
function
关键字会告诉JavaScript
引擎,这段代码的意义是创建一个函数,函数的名称是funcName
,然后括号中的是参数列表,{}
中的内容是函数体。
举个例子:
//函数定义的时候不执行function pow(a,b){let temp = a;while(--b){a *= temp;}console.log(a);}
以上代码创建了一个名为pow
的函数,这个函数可以计算 a b a^b ab。行数在定义的时候不会执行,只有在调用的时候才会执行。
例如,我们计算 2 3 2^3 23,在定义pow
函数后,就可以简单的使用pow(2,3)
实现,如下图:
提醒,这里的幂函数计算方法
pow
并不完善,例如当b=-1时就会死循环
如果我们需要的指数计算较多,就可以重复调用pow
函数,例如:
//函数定义function pow(a,b){let temp = a;while(--b){a *= temp;}console.log(a);}//函数调用pow(2,3)//2的3次方pow(3,4)//3的4次方pow(4,5)//4的5次方
执行结果如下:
这个案例清楚的演示了函数的最主要用途之一,即避免代码重复。
局部变量
局部变量就是定义在函数{}
内部的变量,这些变量只能在函数内部才能使用。
例如,上节课中
for
语句里面的变量i
举个例子:
function doSomething(a,b){let val = prompt('请输入点什么',0);console.log(val);}doSomething();alert(val);//ERROR,这里不能使用val
执行结果如下:
由于变量val
是在函数内部定义的,只能在函数内部使用,外部不能使用函数内部定义的变量。
外部变量
虽然,函数体外不能访问函数体内部定义的变量,但是反过来,函数体内部是可以访问函数体外部定义的外部变量的。
举个栗子:
let val = prompt("请输入点什么",9);function doSomething(){console.log(val);//使用函数体外的变量没有问题}doSomething();
代码执行结果如下:
用户输入的时候,输入了9
内外变量重名
如果内部变量和外部变量具有相同的名字,那么会优先使用内部变量。
举个栗子:
let num = 1;function doSomething(){let num = 2;console.log(num);//这里使用的是内部变量}doSomething();
代码执行结果:
如果一个变量声明在所有函数之外,那么这个变量就是全局变量
程序中声明过多的全局变量不利于程序的优化执行
参数
函数体内部并非完全自治的,很多情况下还是需要一定的输入才能开始执行函数体代码,这个输入就是参数。
举个例子:
function bless(name,senc){console.log(`祝${name}${senc}`)}
代码执行结果:
上例中我们为行数bless
传入了两个参数,分别是人名name
和祝福词senc
,这样就可以像任何人祝福任何话了。
如果我们在函数体内部修改变量,那么外部的变量是否会对应的变化呢?
举个例子:
let a = 1;let b = 2;function exchange(a,b){let temp = a;a = b;b = temp;}console.log(`a=${a},b=${b}`);
代码执行结果:
可以发现,外部变量a
和b
的值并没有改变。
造成这种现象的原因是,传入函数的参数是变量的副本,而不是变量本身。
参数默认值
在定义函数的时候,我们可以为传入的参数设定一个默认值,如果在调用函数的时候为提供参数,就会使用默认值代替。
举个例子:
function bless(name,senc='身体健康'){console.log(`祝${name},${senc}.`);}bless('特朗普');
代码执行结果:
以上函数虽然需要两个参数,但是在调用的时候,传入一个参数并不影响使用,这是因为在定义函数的时候已经为senc
设定了默认值。
如果我们不为参数设定默认值,但是不传入对应参数会发生什么呢?
举个例子:
function bless(name,senc){console.log(`祝${name},${senc}.`);}bless('特朗普');
代码执行结果如下:
可见,在不传递参数情况下,参数是undefined
。
年长代码的默认参数
如果在老版本的JavaScript
中如何使用参数默认值呢?
有两种方式:
使用if
判断:
function doSomething(val){if(val === undefined){val = 'default val';}... ...}
使用||
运算符
function doSomething(val){val = val || 'default val';... ...}
空值合并运算符的应用
即使在现代的JavaScript
中,同样有在函数内部判断是否传入参数的必要,除了上述两种常用于旧代码的方式外,我们还可以使用空值合并运算符:??
。
举个例子:
function doSomething(val){val = val ?? 'unknown';... ...}
返回值
参数是一个函数的输入,而返回值则是一个函数的输出。
返回值需要使用return
关键字,将函数的计算结果返回到函数体外。
最常见的返回值例子莫过于计算两个数字的和:
let a = 1;let b = 2;function add(a,b){return a + b;}let res = add(a,b);
代码执行结果:
以上代码创建了一个函数,用于加和两个变量,然后将结果返回。
在调用函数add
时,通过将返回值赋予变量res
,从而获得返回结果。
我们也可以返回一个空值(什么都不返回):
function doSomething(){console.log('return nothing');return ;//什么都不返回,程序立即结束console.log('after return');}doSomething();
代码执行结果如下:
return
会使程序立即退出,后面的代码不再执行。
一个函数还可以拥有多个返回值:
function mulReturn(score){if(score >= 60){return '及格';}else{return '不及格';}}console.log(mulReturn(30));
代码执行结果:
虽然有多个return
,但是一次执行只会选择一个。
如果函数什么也不返回
return ;
,或者没有return
语句,那么它的返回值就是undefined
return陷阱
当返回表达式比较长时,我们很有可能会将其放在单独一行,如下所示:
return(a + b + c + or + c * f(d) + f(e));
绝不可以这样,因为JavaScript
的分号自动补全机制会在return
后添加;
,从而导致函数永远只会返回undefined
。
如果我们需要处理较长的返回值表达式,应该怎么做呢?
最好的方法就是使用括号:
return (a + b + c+ d + e + f);
然后程序就永远不会出现未知的错误了~~
小技巧
函数通常都是一个行为,因此在命名的时候可以使用“动词+名词”的方式,再结合驼峰式命名法,可以得到一个简洁明了的函数名称,例如:getAge();showMsg();createForm();checkInput();
简化函数功能,一个函数只做一件事,例如:
add(a,b)
函数实现两个数字相加,不应该有例如alert()
的功能;checkInput()
函数应该检测输入合法性,而不应该打印valid invalid
等信息。
过于简短的函数名,会让人不知所云例如:
function a(){...}function b(){...}
但是
JQuery
中的$
不属于此类范畴。
我们应该写出自注释的函数/代码,让代码本身简单、已读。