好程序員web前端學習路線分享函數基礎,在這之前先來講一下函數是什麼?
函數就一個代碼塊,可以是一個完全獨立與其它內容沒有關係的代碼塊,也可以是一個與外界環境緊密相關的代碼塊。函數是一個擁有輸入和輸出的獨立代碼塊。函數是程序中最重要的組成部分。
函數,是一種封裝(將一些語句,封裝到函數裏面)。通過函數可以封裝任意多條語句,而且可以在任何地方、任何時候調用執行。
在javascript裏,函數即對象,程序可以隨意操控它們。函數可以嵌套在其他函數中定義,這樣它們就可以訪問它們被定義時所處的作用域中的任何變量,它給javascript帶來了非常強勁的編程能力。
函數的功能、好處:
1) 將會被大量重複的語句寫在函數裏面,這樣以後需要這些語句的時候,直接調用函數,不用重寫那些語句。
2) 簡化編程,讓編程變的模塊化。
函數的聲明
函數有三種聲明的方法,而且有各自不同的特點。
1、普通函數聲明
函數關鍵字 + 函數名 + (){
語句
函數體
}
例如:
function functionName(){
alert("程序員的搖籃");
// ...語句//
}
注:1.函數命名跟變量一樣,只能是字母、數字、下劃線、美元符號,不能以數字開頭。
2.後邊()裏放參數用的
函數名的規範:
1、普通的函數使用,名稱需要駝峯式命名法,即函數是多個詞組構成時,第一個單詞的首字母小寫,其餘的單詞首字母大寫。函數名不能與關鍵詞和保留字重複,不能與變量名重複。
2、類的構造函數,是駝峯式命名,但是第一個單詞首字母需要大寫。
2、匿名函數聲明
var 變量名稱 = function (){
函數內容
}
var funName=function () {
//函數內容
};
定義一個匿名函數,所謂匿名函數就是沒有函數名。但是匿名函數定義後如果不保存在一個變量中,就找不到了,因此,我們通常會用一個變量接收這個匿名函數。
匿名函數尾部結束時需要用;來結束,普通的函數結束後不用;結束的。
var funName=function abc() {
//函數內容
console.log(abc);
}
匿名函數也是可以定義函數名稱的,只不過比的地方不能使用,只能在函數內部使用。
3、Function構造函數聲明
使用Function構造函數
var box=new Function('num1','num2','retun num1+num2');//num1,num2參數
num1,num2參數, 最後的字符串是函數體
注意:第三種方式我們不推薦,因爲這種語法會導致解析兩次代碼(第一次解析常規JS代碼,第二次是解析傳入構造函數中的字符串),從而影響性能,但我們可以通過這種語法來理解函數是對象,函數名是指針的概念。
函數的存儲
JavaScript程序是一種解釋性語言。那麼什麼時候解釋性語言呢。
計算機其實並不認識程序,不管是什麼代碼計算機都不認識,因爲計算機只是機器,如果我們需要讓計算機認識程序,那麼就需要一個翻譯,就是把程序代碼變成計算機可以理解的語言:0和1的信息序列。目前存在兩種翻譯類型:一個是編譯,一個是解釋。兩種方式都需要對代碼進行翻譯,只是翻譯的時間不同而已。
編譯型語言在計算機運行代碼前,先把代碼翻譯成計算機可以理解的文件,這種文件計算機就能看懂了,但是不管是程序員還是其他人員都看不懂的。並且這種代碼,計算機可以執行了,但是每次我們需要修改代碼時都需要修改源代碼,然後再進行編譯新的文件纔可以使用,也就是不能再編譯好的文件上修改。這種代碼的優勢是運行速度快,在執行前就知道代碼是否錯誤,因爲編譯時就做了判斷。
解釋型語言則不同,解釋型語言的程序不需要在運行前編譯,在運行程序的時候才翻譯,專門的解釋器負責在每個語句執行的時候解釋程序代碼。這樣解釋型語言每執行一次就要翻譯一次,效率比較低。而且執行時才知道代碼是否錯誤。
而JavaScript就是解釋性語言。但是注意程序在運行的時候,解釋器首先會收集所有的普通定義的函數,並且把他們存儲在堆裏,這時候才從頭開始執行代碼。
abc();
function abc() {
}
例如我們看到這裏abc的執行在函數的上面,如果按照代碼的執行順序,應該先執行abc,再創造函數,那麼顯然就會報錯。但是這樣不會有問題。就是說明,函數首先會被收集在堆裏,不管在哪裏調用,都是調用堆裏的函數,因此普通定義的函數執行時可以寫在前面或者寫在後面。
但是注意如果我們使用匿名函數這種情況就不同了。雖然我們會收集匿名函數在堆裏,但是如果找到它時,我們就需要在把它賦給一個變量以後纔可以執行,否則就會報錯。
abc();
var abc=function () {
}
這是錯誤的。
例如上面這種就是錯誤的。
函數的參數
參數是指由外部傳入到函數中的變量,僅作爲變量使用,但是該變量可以是任何內容,包括函數。
被傳入的參數作爲局部變量使用,可以被覆蓋掉。
參數就是一個局部變量,通過外界傳入值,這個參數就是對應的值。參數是按照順序填入的。參數在JavaScript中不要求寫入參數的類型和默認值,如果需要默認值,就需要在函數中,根據條件判斷增加默認的值。有時候我們可以不用定義參數,直接在函數調用時,帶入參數,也可以獲取到。(不建議大家使用)
爲什麼要從外部帶入參數。一般來說函數是獨立處理某段代碼的集合,如果,這段代碼需要重複執行,就會設計出函數,在不同的地方調用,達到代碼共用的目的,減少代碼量。但是在某些時候,雖然是同樣的代碼,但是我們需要它發揮出的作用更大,可以解決不同的問題,這時候,傳入的參數就可以起到代碼干預作用,在同一個函數中解決了很多不同的問題。這時候設計函數的獨立性就顯得非常重要了。當然,任何事情解決都不是絕對的,過度設計複雜的函數有時候反到會讓代碼效率降低。
同時,外部傳入的參數可以節省全局變量的定義,甚至保證函數中的部分變量的獨立性。
參數分爲實參和形參。
實參:真實的數值、字符串
形參:一個接收實參的變量
例如這裏是通過一個函數中的參數來控制在頁面上添加多少個li
var m=5;
createUl(m);
function createUl(n) {
if(n<1 || isNaN(n)) n=1;
var ul="<ul>";
for(var i=0;i<n;i++){
ul+="<li>列表"+(i+1)+"</li>";
}
ul+="</ul>";
document.write(ul);
}
函數的返回值
return 語句會終止函數的執行並返回函數的值。return 是javascript裏函數返回值的關鍵字,一個函數內處理的結果可以使用return 返回,這樣在調用函數的地方就可以用變量接收返回結果。return 關鍵字內任何類型的變量數據或表達式都可以進行返回,甚至什麼都不返回也可以
abc(3,5);
function abc(a,b){
return a+b;
}
注意return只能返回一個值,如果需要返回多個數據時可以考慮數組或者對象,例如
function abc() {
return {a:1,b:2};
}
return 也可以作爲阻止後續代碼執行的語句被使用,例如
var bool=false;
var i=0;
function abc(){
if(bool) return;
i++;
}
這樣可以有效的控制語句在一定的條件下執行,不過一定要與break區分,break是用在條件當中,跳出的也僅僅是條件和循環,但是return 卻可以跳出函數,僅僅是針對函數使用,如果沒有函數是不能使用return的。
abc();
function abc() {
for(var i=0;i<10;i++){
if(i===3){
// break;
return;
}
}
i+=5;
console.log(i);//i=8
}例如上面的例子,如果使用break,就會打印i的值是8,如果使用return,就不會打印了,因爲return直接跳出了函數。
函數的執行
函數的執行分爲兩種
1、普通函數執行
函數執行 :函數名()
執行後,可以完成函數的代碼內容,如果函數內有return 值,這時候執行後會返回該值。
function abc() {
return 3+4;
}
var s=abc();
如何沒有return,則執行完所有代碼
2、函數獨立執行
函數自身是可以獨立執行的,並且也可以把獨立執行的結果賦值給一個變量。
var s=0;
(function(){
s=4+5
})();
左邊是匿名函數自己執行,右邊是匿名函數賦值
注意匿名函數用小括號括住,最後再執行小括號。
注意,除了匿名函數可以獨立執行,實名函數也是可以獨立執行的,不過這種獨立執行就不能在該函數中添加參數了,並且匿名函數,也只能在此執行一次,不能多次調用,顯而易見的好處是,該函數內的變量統統是私有變量,有關該部分內容我們在後面詳細說明
函數的刪除
當函數不在使用時,就需要刪除,函數也是對象,如果不刪除,它將常駐內存中,如果該函數不再使用就可以使用刪除徹底清除掉該函數。但是隻有函數是匿名定義的或者通過構造函數創建的纔可以被刪除。
函數刪除分兩種
1、匿名函數刪除
函數=null
2、對象下函數刪除
delete obj.fun