簡體   English   中英

如何將一個閉包從外部函數中分解出來以在不同的上下文中重用所述閉包?

[英]How can I factor a closure out of an outer function to reuse said closure in different contexts?

假設我有一些處理事件處理的代碼。

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單擊btn1result1中顯示“hello”。

Uppon點擊btn2result2中顯示“YO”。

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

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函數沒有在sayshout函數中聲明; 因此, 容器將不會被定義。

我曾嘗試用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);
}

但這也不起作用。


如何將sayEvent函數從sayshout函數中分解出來?

謝謝!

JsBin設置

您不能在不同的上下文中重用閉包,因為根據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);
    };
}

或者如果你想使用bind:

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);
}

如果您創建了要綁定的新對象,則綁定應該有效,而不是使用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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM