13 函數語言程式設計
當我們想要使用一個函式時,其實就是想將一些功能、邏輯等封裝起來以便使用。相信您對於封裝這個概念並不陌生,我們經常使用函式封裝來做一些想要做的事情。
例如,若想計算任意三個數的和,就可以將這個三個數作為引數封裝成一個簡單的函式。
function add(a,b,c) {
return a + b + c;
}複製程式碼
當再次需要計算三個數的和時,直接呼叫該函式即可。
add(1,2,3)複製程式碼
一般來說,當想要做的事情比較簡單時,可能還看不出封裝成函式之後會帶來的便利。如果想要做的事情稍微複雜一點呢,例如想要計算一個陣列中所有子項的和。
function mergeArr(arr) {
var result = 0;
for(var i = 0; i++; i<arr.length) {
result += arr[i];
}
return result;
}複製程式碼
如果不通過封裝成函式的方式,而是每次都用for迴圈去計算陣列中所有子項的和,那麼程式碼量肯定就會偏多。封裝之後,當再次做這件事情的時候,只需要用一句程式碼即可。
mergeArr([1,2,34]);複製程式碼
函式封裝的意義現在已非常明確,但面臨的問題是,當想要去封裝一個函式時,怎麼做才是最好的呢?
如果沒有認真想過這個問題,那麼你封裝的函式可能會非常的糟糕。也許使用起來並不是那麼好用,甚至可能會導致你的程式裡出現無法預知的bug。因此實踐中在做函式封裝的時候,你我都有必要學習一些優秀的封裝習慣,來讓自己的程式碼看上去更加的專也與可靠。
so,讓我們開始學習函式的封裝思維把——函數語言程式設計。
與函數語言程式設計相對應的叫作指令式程式設計。這也是我們初學程式碼時,經常使用的方式。
下面我們用一個簡單的例子來區分這兩種不同的思維把。
我們在實踐中常常需要處理不同的資料,假設這個時候有一個陣列,我們需要找出該陣列中所有型別為number的子項。
當我們使用指令式程式設計,寫出如下程式碼:
var arr = [1,2,'343','asf',234];
var res = [];
for(var i = 0; i< arr.length; i++) {
if (typeof arr[i] === 'number'){
res.push(arr[i]);
}
}複製程式碼
在這種實現方式中,簡單粗暴的表達我們的意思。這樣做的問題在於,當另一個場景,出現了同樣的需求,或者需要將另一個陣列的中的number子項也找到,那麼我們不得不重寫一遍,因此這個時候程式碼就變得非常難以維護。
而函數語言程式設計的思維則是當遇到這種場景時,把邏輯封裝起來。
function getNumbers(array) {
var res = [];
array.forEach(function(item) {
if(typeof item === 'number') {
res.push(item);
}
})
return res;
}
//以上是封裝,以下是功能實現
var array = [1,2,3,'3333'];
var res = getNumbers(array);複製程式碼
在函數語言程式設計實踐中,我們封裝了一個工具方法,專門用來找出一個陣列中的所有number。而我們真正需要維護的程式碼只有兩行。我們只需知道getNumbers這個工具方法能做什麼即可,不必關係他是如何實現的。
在現實生活中這種思維場景非常多久,我們去飯店吃飯點菜,不必關係廚房是如何做出來,只要盡情享受美食即可。這種更加關心結果的思維方式,就是函式程式設計。
13.1 函式是一等公民
所謂的“一等公民”,其實就是普通老百姓。也就是說,函式其實沒有什麼特殊的,我們可以像對待任何其他資料型別一樣對待函式。
1、可以把函式賦值給一個變數。
var fn = function() {}複製程式碼
2、也可以把函式當作引數。
function fn(callback) {
var a = 20;
return callback(20, 30) + a;
}
function add(a, b) {
return a + b;
}
fn(add); //70複製程式碼
3、還可以把函式作為另一個函式執行的返回值。
function add(x) {
var y = 20;
return function() {
return x + y;
}
}
var _add = add(100);
_add(); //120複製程式碼
其實這些都是javascript的基本概念啦,但是看身邊很多同仁好像都不怎麼重視。那我們下面用一個簡單的例子來證明一下。
首先自定義一個這樣的函式(如下),要求在5000ms之後執行該函式,我們應該怎麼做?建議思考10s再往下看。
function delay() {
console.log('5000ms後執行');
}複製程式碼
有人可能會這樣寫。
var timer = setTimeout(function() {
delay();
},5000);複製程式碼
很顯然,這樣做能夠達到我們的目的,但這也正是我們忽視了上面的那些基礎概念。
函式既然能夠作為一個引數傳入另一個函式,那麼是不是可以直接將delay函式傳入,而不用在固有的思維上額外在封裝一層多的的function呢?
var timer = setTimeout(delay, 5000);複製程式碼
當然,如果你已經想到這麼做,那麼恭喜你。
其實,第一種寫程式碼的方式,我相信在未來還會遇到很多次,我們需要一直修煉自己。好了再來一個例子。
function getUser(path, callback) {
return $.get(path, function(info){
return callback(info);
})
}
getUser('/api/user',function(res){
console.log(res);
})複製程式碼
您不妨寫下您的優化方案,我們一起探討。
這些都是我以往的學習筆記。如果您看到此筆記,希望您能指出我的錯誤。有這麼一個群,裡面的小夥伴互相監督,堅持每天輸出自己的學習心得,不輸出就出局。希望您能加入,我們一起終身學習。歡迎新增我的個人微訊號:Pan1005919589