JavaScript 函數(shù)式編程中的引用函數(shù)、調(diào)用函數(shù)和回調(diào)函數(shù)
閱讀本文前先閱讀《JavaScript 中的匿名函數(shù)》可以更好的理解本文。
1. 引用函數(shù)與調(diào)用函數(shù)的區(qū)別
引用函數(shù)與調(diào)用函數(shù)的差別與函數(shù)名稱后是否帶有括號(hào) () 有關(guān)。函數(shù)引用只會(huì)單獨(dú)出現(xiàn),但函數(shù)調(diào)用則必定后面帶有括號(hào),很多時(shí)候還附有參數(shù)。
舉個(gè)例子(本示例是個(gè) QML 示例,但是 JS 功能一致):
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Text {
id: output
anchors.centerIn: parent
}
function f1(){
var x = 5;
return x;
}
function f2() {
var x = 5;
return x;
}
function f3(){
var x = 5;
return function(){
return x;
}
}
Component.onCompleted: {
var result = ""
var a1 = f1;
var b1 = f1;
result += "a1====" + a1 + "\n"
result += "b1====" + b1 + "\n\n"
result += "a1 === b1 result=====> " + (a1 === b1) + "\n\n"
var a2 = f2();
var b2 = f2();
result += "a2====" + a2 + "\n"
result += "b2====" + b2 + "\n\n"
result += "a2 === b2 result=====> " + (a2 === b2) + "\n\n"
var a3 = f3();
var b3 = f3();
result += "a3====" + a3 + "\n"
result += "b3====" + b3 + "\n\n"
result += "a3 === b3 result=====> " + (a3 === b3) + "\n\n"
var a4 = function() {
x = 8;
return x;
}
var b4 = function() {
x = 8;
return x;
}
result += "a4====" + a4 + "\n"
result += "b4====" + b4 + "\n\n"
result += "a4 === b4 result=====> " + (a4 === b4) + "\n\n"
result += "a3()====" + a3() + "\n"
result += "b3()====" + b3() + "\n\n"
result += "a3() === b3() result=====> " + (a3() === b3()) + "\n"
output.text = result
}
}
上面示例的輸出結(jié)果:

如上的示例代碼中:代碼 a1b1 和代碼 a2b2 分別是函數(shù)引用和函數(shù)調(diào)用的列子,返回都為true,代碼 a3b3 是函數(shù)調(diào)用的列子,代碼 a4b4 是函數(shù)引用的列子,返回都為 false。
我們現(xiàn)在來(lái)理解下函數(shù)引用和函數(shù)調(diào)用的本質(zhì)區(qū)別:當(dāng)引用函數(shù)時(shí)候,多個(gè)變量?jī)?nèi)存存儲(chǔ)的是函數(shù)的相同的入口指針,因此對(duì)于同一個(gè)函數(shù)來(lái)講,無(wú)論多少個(gè)變量引用,他們都是相等的,因?yàn)閷?duì)于引用類型(對(duì)象,數(shù)組,函數(shù)等)都是比較的是內(nèi)存地址,如果他們內(nèi)存地址一樣的話,說(shuō)明是相同的;但是對(duì)于函數(shù)調(diào)用來(lái)講,比如代碼 a3b3,每次調(diào)用的時(shí)候,都被分配一個(gè)新的內(nèi)存地址,所以他們的內(nèi)存地址不相同,因此他們會(huì)返回 false,但是對(duì)于代碼 a2b2 來(lái)講,我們看到他們沒(méi)有返回函數(shù),只是返回?cái)?shù)值,他們比較的不是內(nèi)存地址,而是比較值,所以他們的值相等,因此他們也返回 true,我們也可以看看如下實(shí)列化一個(gè)對(duì)象的列子,他們也被分配到不同的內(nèi)存地址,因此他們也是返回 false 的;如下代碼測(cè)試:
function F(){
this.x = 5;
}
var a = new F();
var b = new F();
console.log(a === b); // false
- 函數(shù)與一般變量的差異,在于如何使用數(shù)據(jù)。與函數(shù)相關(guān)的數(shù)據(jù)(或代碼)可被執(zhí)行。想執(zhí)行函數(shù)時(shí),就在函數(shù)名稱后加上括號(hào)
(),如果函數(shù)需要變量,也要記得附加上。 - 函數(shù)變量的值不是代碼本身,而是指向存儲(chǔ)代碼的存儲(chǔ)器位置的引用。
2. 回調(diào)函數(shù)
簡(jiǎn)單理解就是:函數(shù) a 有一個(gè)參數(shù),這個(gè)參數(shù)是個(gè)函數(shù) b,當(dāng)函數(shù) a 執(zhí)行完以后執(zhí)行函數(shù) b。那么這個(gè)過(guò)程就叫回調(diào)。下面是一段 QML 測(cè)試代碼:
function a(callback) {
console.log("我是parent函數(shù)a!");
console.log("調(diào)用回調(diào)函數(shù)");
callback();
}
function b(){
console.log("我是回調(diào)函數(shù)b");
}
function c(){
console.log("我是回調(diào)函數(shù)c");
}
function test() {
a(b);
a(c);
}
Component.onCompleted: {
test()
}
上面的測(cè)試代碼的輸出結(jié)果:

實(shí)際上,結(jié)合 JavaScript 中的匿名函數(shù) 這篇,將對(duì)象的概念引入一起理解,會(huì)發(fā)現(xiàn)上面的那些不相等的情況,實(shí)際上是因?yàn)椴煌膶?duì)象進(jìn)行比較,不相等是必然的。