6.1 函数的概念
为什么需要用函数?
首先看一下输出100所有素数问题的解决方案
方案一:循环的嵌套
<script>
for (var n=2; n<=100; n++) {
var m = Math.ceil(Math.sqrt(n));//根据相关数学定理,查找范围可缩小至[2,sqrt(n)]
var found = false;//找到因子的标记
for (var i = 2; i <= m; i++) {
if (n % i == 0) {
found = true;
break;//找到则提前结束
}
}
if (!found) {
document.write(n + "是素数
");
}
}
script>
这种解决方案程序比较复杂,阅读也比较困难,需要比较高超的技术。
方案二:应用函数
<script>
for(var n=2; n<100; n++){
if(isPrime(n)){
document.write(n+"
");
}
}
function isPrime(n){
var m = Math.ceil(Math.sqrt(n));//根据相关数学定理,查找范围可缩小至[2,sqrt(n)]
var found = false;//找到因子的标记
for (var i = 2; i <= m; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
script>
这种解决方案是将一个比较复杂的问题分解为两个较为简单的问题去解决,是用“量”去克服“难”和“大”的问题。
这种解决方案给我们提供了一个解决规模大、难度高的问题的解决思路:将它分解为多个规模相对较小、难度相对较低的问题去解决,如果分解后的问题依然规模大或者难度高,可以按照这个思路一直分解下去,直到分解后的问题足够小、简单。归纳起来就是“大事化小”。
6.2 定义与调用
函数是是什么,怎么用?
定义:
function isPrime(n){
……
}
function 定义函数的关键字
isPrime 是函数的名字,和变量名一样的命名规则和原则
n 形式参数(形参)
函数调用:
isPrime(12)
12就是实际参数(实参)
函数头部,体现的是函数的设计
函数体,体现的是函数的实现过程
设计比实现更重要
案例:验证100以内的数都符合角谷定理
<script>
var flag = true;
for(var n=2; n<=100; n++){
if(!isJiaogu(n)){
flag = false;
}
}
alert("角谷定理验证"+(flag?"成功":"失败"));
/*
* 功能:判断一个给定的数是否符合角谷定理
* 名称:isJiaogu
* 输入参数:待判断的数
* 输出结果:true/false
* */
function isJiaogu(n){
while(n != 1){
if(n%2 == 0){
n /= 2;
}else{
n = n*3+1;
}
}
return true;
}
script>
案例:验证10000以内哥德巴赫猜想成立
函数的本质:直观理解就是实现某个独立功能的代码段,或者说它就是一个数据加工的黑箱子
所谓“黑箱子”,就是我们只关心外面的东西,比方说它是干啥的,需要输入什么,可以得到什么结果,而不关心里面是怎么工作的。
忽略实现细节
6.3 参数传递
所谓参数传递,就是将实参的值传递给形参。通过调试可以确定形参在函数被调用之前是不存在的,当函数被调用的那一刻,实参被创建,并且把实参的值传递给形参。
参数传递有两种方式:值传递和引用传递
<script>
var a = 5;
increase(a);
alert(a);
function increase(x){
x++;
}
script>
a的值并没有显示预期中的6,还是5。因为形参x和实参a是两个不同的变量,x的变化和a没有任何关系。
引用传递
var a = new Object();
a.value = 5;
increase(a);
alert(a.value);
function increase(x){
x.value++;
}
a.value没有被显式修改,但是a.value确实是加1了,因为x就是a,或者说x是a的别名,专业一点就叫引用。
常规类型的参数采用的是值传递,比如Number、String、Boolean
对象类型采用的是引用传递,Object。
如果希望把参数从函数中带出来,但是函数的返回值只有一个
6.4 变量作用域
局部变量:在函数内部定义的变量,这个变量只能够在函数的内部使用,在全局中不能够使用。比如在三国时期,袁术称帝后,只有袁术阵营的人才认为他是皇帝,他发布的命令只有在本阵营里面起作用。但是其他人不认为他是皇帝,他发布的命令没有作用。
function localVar(){
var a = 1;
alert(a);
}
localVar();
alert(a);
在函数内部定义一个变量,如果没有加上var ,那么这个变量被认作为全局变量。
function localAllVar(){
a = 1;
}
function test(){
alert(a);
}
localAllVar();
test();
全局变量:在函数外部定义的变量,这个变量可以在全局进行使用。比如汉朝的皇帝发布了命令,那么不管是袁绍还是曹操都要听这个命令。
var a = 1;
function allVar(){
alert(a);
}
allVar();
冲突处理原则:就近原则。
当函数中定义了一个和全局变量名相同的变量,此时在函数中在定义前使用,那么这个变量还是函数中的变量,为undefined,不使用全局变量。
要理解就近原则,而不是从上到下。
var a = 1;
function doubleVar(){
var a = 2;
var a = 3;
alert(a);
}
局部和全局同时定义了一个相同名字的变量时如何在局部里面访问全局变量?在局部中给变量加上window的前缀,就可以访问到全局的变量。
var a = 1;
function doubleVar(){
var a = 2;
var a = 3;
alert(a);
alert(window.a);
}