函数
1.1函数的概念:
为什么需要用函数?
首先看一下输入100以内所有素数问题的解决方案
方案一:循环的嵌套:
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+ "是素数");
}
}
这种解决方案程序比较复杂,阅读也比较困难,需要比较高超的技术。
方案二:应用函数
for(var n = 2; n <= 100;n++){
if(isPrime(n)){
document.write(n+"<br>");
}
}
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;
}
这种解决方案是将一个比较复杂的问题分解为两个比较简单的问题去解决。使用“量”去克服“难”和“大”的问题。
这种解决方案给我们提供了一个解决规模大、难度高的解决思路:将它分解为多个规模相对较小、难度相对较低的问题去解决,如果分解后的问题依然规模大或者难度高,可以按照这个思路一直分解下去,直到分解后的问题足够小,简单,
归纳起来也就是“大事化小”。
1.2定义与调用
定义:
function isPrime(n){
………
}
function:定义函数的关键字
isPrime:是函数的名字,和变量名一样的命名规则和原则。
n:形式参数(形参)
isPrime(12),12就是实际参数(实参)
函数头部:体现的是函数的设计
函数体:体现的是函数的实现过程
设计比实现更加重要
案例:验证100以内的数都符合角谷定理
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;
}
案例:验证10000以内哥德巴赫猜想成立。
我们要先假设有这样一个函数,当有了这样一个函数我们怎么用呢?
首先我们要告诉系统我们要判断的对象:6-10000的偶数,然后做一个标记,
输出哥德巴赫猜想能否是否验证成功。
/*
* 假设系统有一个函数能帮我们判断大于6的偶数能否分解的话
* 设计一下该函数
* */
/*
* 功能:判断一个数能否分解为两个素数之和
* 名称:canSplit
* 输入参数:待分解的数
* 返回结果:true/false
* */
var flag = true ;//标记
for(var n =6; n <= 10000; n+=2){//6-10000之间的偶数
if (!canSplit(n)){
flag = false;
break;
}
}
alert("哥德巴赫猜想验证"+(flag?"成功":"失败"));
函数的本质:直观理解就是实现某个独立功能的代码段,或者说他就是一个给数据加工的黑箱子
所谓“黑箱子”,就是我们只关心外面的东西,比方说它是干啥的,需要输入什么,可以得到什么结果,而不关心里面是怎么工作的。
忽略实现的细节
1.3参数传递
所谓参数传递,就是将实参的值传递给形参。通过调试可以确定形参在被调用之前是不存在的,当函数被调用的那一刻,实参被创建,并且把实参的值传递给形参。
参数传递有两种方式:值传递和引用传递
var a =5;
increase(a);
alert(a);
function increase(x){
x++;
}
a的值并没有显示预期中的6,因为形参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)
全局变量:在函数外部定义的变量,这个变量可以在全局进行使用,比如汉朝的皇帝发布了命令:那么不管是袁绍还是曹操都要听这个命令。
冲突处理原则:就近原则。
当函数中定义了一个和全局变量名相同的变量,此时在函数中在定以前使用,那么这个变量还是函数中的变量,为undefined,不使用全局变量。
要理解就近原则,而不是从上到下。
var a = 1;
function test(){
alert(a);
var a = 2;
alert(a);
}
test();
alert(a);
var a = 1;
function allvar(){
alert(a);
}
allvar();
局部和全局同时定义了一个相同名字的变量时如何在局部里面访问全局变量?在局部中给变量加上Window的前缀就可以访问到全局的变量。
var a = 1;
function doublevar(){
var a = 2;
var a = 3;
alert(a);
alert(window.a);
}
doublevar();
在函数内部定义一个变量,如果没有加上var,那么这个变量被认作为全局变量。
function LocalAllval(){
a = 1;//不加var 就会变成全局变量
}
LocalAllval();
function test (){}
test();
alert(a);