函數
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);