2016-04-07 54 views
1

假設我有這樣的代碼處理事件處理。

var btn1 = document.getElementById('btn1'); 
var btn2 = document.getElementById('btn2'); 

btn.addEventListener('click', say('hello')); 
btn2.addEventListener('click', shout('yo')); 

function say(word) { 
    var saying = word; 
    var container = document.getElementById('result1'); 
    return function handleEvent() { 
     var text = document.createTextNode(saying); 
     container.innerHTML = ''; 
     container.appendChild(text); 
    }; 
} 

function shout(word) { 
    var saying = word.toUpperCase(); 
    var container = document.getElementById('result2'); 
    return function handleEvent() { 
     var text = document.createTextNode(saying); 
     container.innerHTML = ''; 
     container.appendChild(text); 
    }; 
} 

Uppon點擊BTN1, 「你好」 顯示在RESULT1如何從外部函數中重新構造閉包以在不同的上下文中重用閉包?

Uppon點擊btn2,「YO」顯示在result2

現在,您可能已經注意到,這兩個函數完全相同。我想要達到的是類似的東西。

function say(word) { 
    var saying = word; 
    var container = document.getElementById('result1'); 
    return handleEvent; 
} 

function shout(word) { 
    var saying = word.toUpperCase(); 
    var container = document.getElementById('result2'); 
    return handleEvent; 
} 

function handleEvent() { 
    var text = document.createTextNode(saying); 
    container.innerHTML = ''; 
    container.appendChild(text); 
} 

但隨着的handleEvent函數未聲明裏面函數,當然是行不通的;因此,容器將不會被定義。

我曾嘗試在玩弄bind()的並宣佈容器這個裏面說功能:

function say(word) { 
    this.saying = word; 
    this.container = document.getElementById('result1'); 
    return handleEvent.bind(this); 
} 

function shout(word) { 
    this.saying = word.toUpperCase(); 
    this.container = document.getElementById('result2'); 
    return handleEvent.bind(this); 
} 

function handleEvent() { 
    var text = document.createTextNode(this.saying); 
    this.container.innerHTML = ''; 
    this.container.appendChild(text); 
} 

但是沒」不管工作。


我怎樣才能因式分解的handleEvent功能出了的功能呢?

謝謝!

JsBin setup

回答

0

綁定應該有工作,如果你創造要綁定的新對象,而不是使用this

function say(word) { 
    return handleEvent.bind({ 
     saying: word, 
     container: document.getElementById('result1') 
    }); 
} 

function shout(word) { 
    return handleEvent.bind({ 
     saying: word.toUpperCase(), 
     container: document.getElementById('result2') 
    }); 
} 

但是,你仍然可以正常關閉解決這個問題:

function say(word) { 
    return makeHandleEvent(word, 'result1'); 
} 

function shout(word) { 
    return makeHandleEvent(word.toUpperCase(), 'result2'); 
} 


function makeHandleEvent(saying, id) { 
    var container = document.getElementById(id); 
    return function handleEvent() { 
     var text = document.createTextNode(saying); 
     container.innerHTML = ''; 
     container.appendChild(text); 
    } 
} 
0

不能重用在不同的上下文中的閉合,因爲根據定義在JavaScript的封閉是這勢必其父的上下文內的功能。

但是,您可以提取函數體內,以便重複使用在不同的上下文:

var btn1 = document.getElementById('btn1'); 
var btn2 = document.getElementById('btn2'); 

btn.addEventListener('click', say('hello')); 
btn2.addEventListener('click', shout('yo')); 

function saySomething(context, saying) { 
    var text = document.createTextNode(saying); 
    container.innerHTML = ''; 
    container.appendChild(text); 
}; 

function say(word) { 
    var saying = word; 
    var container = document.getElementById('result1'); 
    return function handleEvent() { 
     saySomething(context, saying); 
    }; 
} 

function shout(word) { 
    var saying = word.toUpperCase(); 
    var container = document.getElementById('result2'); 
    return function handleEvent() { 
     saySomething(context, saying); 
    }; 
} 

或者,如果你想使用綁定:

var btn1 = document.getElementById('btn1'); 
var btn2 = document.getElementById('btn2'); 

btn.addEventListener('click', say('hello')); 
btn2.addEventListener('click', shout('yo')); 

function saySomething(context, saying) { 
    var text = document.createTextNode(saying); 
    container.innerHTML = ''; 
    container.appendChild(text); 
}; 

function say(word) { 
    var saying = word; 
    var container = document.getElementById('result1'); 
    return saySomething.bind(undefined, context, saying); 
} 

function shout(word) { 
    var saying = word.toUpperCase(); 
    var container = document.getElementById('result2'); 
    return saySomething.bind(undefined, context, saying); 
} 
+0

我想一個小的變化將以上學歷。 你必須調用saySomething(context,說)而不是將它作爲閉包返回。通過將它作爲閉包返回,saySomething()函數根本不會被執行。 – rajesh

+0

閉包返回,因爲addEventListener使用它作爲處理程序。你需要它。與綁定相同。你不想實際上從說或喊的內部調用saySomething,你只是希望它返回並綁定到他們的上下文。 –

+0

綁定將以您提及的方式正常工作。但不是第一個。代碼將返回一個執行它的函數。所以它永遠不會進入功能saySomething。我想你已經忽略了它。 – rajesh

相關問題