|
|
|
|
|
在 JavaScript 中,事件偵聽器(addEventListener
)常常被用到,例如對某按鈕的點(diǎn)擊這一事件上。addEventListener
函數(shù)與標(biāo)準(zhǔn)函數(shù)的執(zhí)行方式不同,在本文中,我將通過實(shí)例介紹事件偵聽器addEventListener
功能參數(shù)的使用。
在 JavaScript 中,有兩種方法可以“調(diào)度執(zhí)行”函數(shù):
myFunc()
e.addEventListener('click', )myFunc()
你注意到區(qū)別了嗎?方式1是當(dāng)腳本加載解析到它時(shí),會(huì)立即去執(zhí)行(調(diào)用)一個(gè)函數(shù),而方式2卻沒有這樣。
我們看下面的代碼片段:
function init() {
// code
console.log("JavaScript Is Love!!")
}
init();
上面的代碼片段定義了一個(gè)函數(shù) ( init),在該函數(shù)內(nèi)部我們執(zhí)行一些隨機(jī)代碼。
當(dāng)然,init
里面的代碼并不會(huì)在腳本加載解析的時(shí)候立即執(zhí)行,它只在函數(shù)被調(diào)用時(shí)執(zhí)行——使用后面的init()
調(diào)用。
使用addEventListener的案例
下面的案例與上面的不同,我們看看代碼。
function greet() {
alert('你好!');
}
someButton.addEventListener('click', greet);
請注意最后一行,greet
是沒有括號的,不是greet()
。
如果添加括號 ( greet()
),將執(zhí)行該函數(shù)。這意味著,一旦 JavaScript 執(zhí)行到達(dá)這一行,greet
函數(shù)內(nèi)部的代碼就會(huì)立即運(yùn)行:
someButton.addEventListener('click', greet());
但這通常不是你想要的。當(dāng) JavaScript 到達(dá)這一行時(shí),你不想立即執(zhí)行greet
,而是希望它在單擊按鈕 ( someButton
) 時(shí)執(zhí)行。
參考與函數(shù)結(jié)果
在“標(biāo)準(zhǔn)情況”(或稱之為直接函數(shù)執(zhí)行)中,只是簡單地指示 JavaScript 執(zhí)行函數(shù)內(nèi)部的代碼。
這就是我們在本文的第一個(gè)示例中所做的:
function init() {
// 代碼
const myElement = document.createElement('li');
myList.append(myElement);
}
init();
在第二種情況下(使用按鈕和事件偵聽器addEventListener
),不是直接執(zhí)行函數(shù),而是“間接地”執(zhí)行它——通過點(diǎn)擊按鈕來調(diào)用。
因此不能在greet
之后添加()
,因?yàn)槟菚?huì)立即調(diào)用該函數(shù)。
只需使用
someButton.addEventListener('click', greet);
我們只是“指向”函數(shù),我們將函數(shù)的引用作為第二個(gè)參數(shù)傳遞給addEventListener
。
如果代碼改為這樣
someButton.addEventListener('click', greet());
這不是為addEventListener
引用greet
,而是調(diào)用greet()
的結(jié)果。
那是什么結(jié)果?好吧,就是這個(gè)函數(shù)返回的任何東西。在這個(gè)例子中,這是undefined
,因?yàn)楹瘮?shù)沒有返回任何東西。如果它有一個(gè)return
聲明,它將是return
后面的任何內(nèi)容。
引用和功能參數(shù)
但如果greet
看起來像這樣呢?
function greet(name) {
alert('Hi ' + name);
}
現(xiàn)在它變得有點(diǎn)棘手。greet
想要一個(gè)參數(shù)(name),我們“連接”greet
到按鈕,如下所示:
someButton.addEventListener('click', greet);
JavaScript 如何知道應(yīng)該輸入哪個(gè)name值?
答案是:沒有。
目前,如果單擊按鈕,只會(huì)得到Hi undefined
輸出。顯然不是我們想要的!
這個(gè)問題有兩個(gè)簡單的解決方案:
someButton.addEventListener('click', function () {
greet('Max'); // 產(chǎn)生 'Hi Max'
});
someButton.addEventListener('click', greet.bind(null, 'Max')); // 也產(chǎn)生 'Hi Max'
這會(huì)發(fā)生什么?
讓我們從解決方案 1開始。
在那里,我們創(chuàng)建了一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)作為addEventListener
第二個(gè)參數(shù)。
當(dāng) JavaScript 到達(dá)該行時(shí),它不會(huì)立即執(zhí)行,因?yàn)槲覀儧]有在匿名函數(shù)定義之后添加括號。
在該函數(shù)內(nèi)部,我們?nèi)缓笳{(diào)用greet('Max')
,但請記住,此代碼僅在單擊按鈕后執(zhí)行(因?yàn)樗荒涿瘮?shù)包裝)。
這就是解決方案 1,現(xiàn)在讓我們看看解決方案 2。
在那里,我們使用bind()
方法。bind()
方法在函數(shù)對象上可用——為此,重要的是要記住函數(shù)也是 JavaScript 中的對象。
bind()
方法有什么作用?它“準(zhǔn)備”調(diào)用將來執(zhí)行的函數(shù)。它允許“預(yù)配置”該函數(shù)在最終被調(diào)用時(shí)應(yīng)接收的參數(shù)。此外,還可以定義this
關(guān)鍵字引用該函數(shù)內(nèi)部的內(nèi)容。參考文章:
準(zhǔn)確地說,當(dāng)我們這樣使用bind()
時(shí),
someButton.addEventListener('click', greet.bind(null, 'Max')); // 也產(chǎn)生 'Hi Max'
我們告訴 JavaScript this
是 null
(沒有任何值),并且在greet
調(diào)用它時(shí)傳遞給第一個(gè)參數(shù)值是Max。
你可以簡單地記住,bind
第一個(gè)參數(shù)始終是this
關(guān)鍵字引用,之后的所有其他參數(shù)都是將被調(diào)用的函數(shù)的參數(shù)(即bind
調(diào)用的函數(shù))。
因此,“待調(diào)用 ”函數(shù)的第一個(gè)參數(shù)將得到傳遞給bind
的第二個(gè)參數(shù)。“待調(diào)用”函數(shù)的第二個(gè)參數(shù)將通過傳遞給bind
的第三個(gè)參數(shù)來定義。等等。
并且通過使用此代碼,我們確保在將來調(diào)用它時(shí),Max將作為greet
接收的一個(gè)值。
總結(jié)
本文詳細(xì)介紹了JS事件監(jiān)聽器 addEventListener
使用的兩種方法,使用哪種取決于你喜歡哪種方法(匿名函數(shù)與bind
綁定),最重要的部分是你要了解為什么需要這些方法。
在文章中,我們還指出了使用addEventListener
時(shí)容易寫錯(cuò)的地方,需要特別注意。