JavaScript淺嚐紀錄No.6-函式封裝(Encapsulation)?回調(Callback Function)?

函式

結構

請先參考JavaScript淺嚐紀錄No.2-JS的中變數、函式的潛規則,就不再贅述了。
function

封裝(Encapsulation)

在上Alpha Camp線上課程時,發現了一個特殊的名詞封裝,一開始並不是很注意這個名詞,但是在寫筆記想介紹封裝時,卻發現解釋不出來他的定義,於是又開始了大量查找資料的旅程,但還是只能簡單的介紹,讓自己先有個概念。

在MDN上對於封裝有這樣的解釋:

Encapsulation is the packing of data and functions into one component (for example, a class) and then controlling access to that component to make a “blackbox” out of the object. Because of this, a user of that class only needs to know its interface (that is, the data and functions exposed outside the class), not the hidden implementation.
另一個簡短的介紹:將資料與方法包裝在一起使用。

1
2
3
4
5
6
7
8
9
10
11
12
function hotel(name, rooms, booked) {
this.name = name
this.rooms = rooms
this.booked = booked
this.available = function () {
return this.rooms - this.booked
}
}
let WHotel = new hotel('WHotel', 100, 30)
let SHotel = new hotel('SHotel', 140, 50)
console.log(WHotel) //{name: "WHotel", rooms: 100, booked: 30, available: ƒ}
console.log(SHotel) //{name: "SHotel", rooms: 140, booked: 50, available: ƒ}

上面程式碼中,利用建構函式來創建WhotelSHotel,但是WhotelSHotel並不會知道算出剩餘房間(available)的程式碼,它們只是能夠使用該方法,這個概念就是封裝(Encapsulation)。

封裝的目的是甚麼?
讓使用者不會更動到原始程式碼,甚麼意思?請看下面程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
function hotel(name, rooms, booked) {
this.name = name
this.rooms = rooms
this.booked = booked
this.available = function () {
return this.rooms - this.booked
}
}
let WHotel = new hotel('WHotel', 100, 30)
let SHotel = new hotel('SHotel', 140, 50)
WHotel.name = 'PHotel'
console.log(WHotel) //{name: "PHotel", rooms: 100, booked: 30, available: ƒ}
console.log(SHotel) //{name: "SHotel", rooms: 140, booked: 50, available: ƒ}

利用WHotel.name = 'PHotel'變更WHotel的名字,但是SHotel並不會受到WHotel改名的影響,創建出來的變數WHotelSHotel不論有何變動,都不會影響到原始程式碼function hotel(){...}的內容,這就是封裝的概念,確保使用者無法任意更改物件內部的重要資料。

參考資料:
MDN-JavaScript 物件導向介紹
維基百科-封裝 (物件導向程式設計)
李重楼-JavaScript的封装

回調(Callback Function)

JavaScript Is Sexy裡的介紹:

A callback function, also known as a higher-order function, is a function that is passed to another function (let’s call this other function “otherFunction”) as a parameter, and the callback function is called (or executed) inside the otherFunction.
When we pass a callback function as an argument to another function, we are only passing the function definition. We are not executing the function in the parameter.Note that the callback function is not executed immediately. It is “called back” (hence the name) at some specified point inside the containing function’s body.

也就是說A函示是作為參數值(argument)被傳給B函示(又被稱作higher-order function),並且這個A函示只有在指定的狀況才會執行。

1
2
3
4
var friends = ["A", "B", "C", "D"];
friends.forEach(function (friend, index){
console.log(index + 1 + ". " + friend);
});

forEach()之後執行裡面的匿名函式,這樣的概念也就是**回調(Callback function)**。

在jQuery中也運用很多回調:

1
2
3
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});

click()之後執行裡面的匿名函式。
千萬不能在function() {alert("Btn 1 Clicked");}之後加上(),這樣會變成馬上執行這個function

上面用的都是匿名函式,當然也可以使用命名函式來做回調函式,同樣的不能在作為引數時加上()

1
2
3
4
5
6
7
8
function study(name) {
console.log(`${name} is STUDYING !`)
}
function eat(name,callback) {
console.log(`${name} is EATING !`)
callback(name)
}
eat('Mark',study)

函式eat執行完之後會執行函式study,並且可以在callback(parameter)中放入參數,執行函式eat時會將該參數值再帶入函式study裡當成引數喔。

JavaScript Is Sexy-Understand JavaScript Callback Functions and Use Them,有看到一個建議:在執行Callback Function時要先確定Callback是一個函式。
如下:

1
2
3
4
5
6
7
8
9
10
11
12
function study(name) {
console.log(`${name} is STUDYING !`)
}
function eat(name,callback) {
console.log(`${name} is EATING !`)
// Make sure the callback is a function
if (typeof callback === "function") {
// Call it, since we have confirmed it is callable
callback(name);
}
}
eat('Mark',study)

參考資料:
JavaScript Is Sexy-Understand JavaScript Callback Functions and Use Them
菜鳥工程師 肉豬-JavaScript 什麼是Callback函式 (Callback Function)?