6函數
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
+ "是素數<br>");
}
}
</script>
這種解決方案程序比較複雜,閱讀也比較困難,需要比較高超的技術。
方案二:應用函數
<script>
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;
}
</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);
}