繁体   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