如何更改事件处理程序中传递的变量

How to change passed variable inside event handler

我想知道是否有办法通过处理事件来更改 "external" 变量

function generateHTML()
{
    var html = '';

    // Some html generating code
    html += '<b>John Doe</b>';

    $(document).trigger('html:generating', html);

    // Do more hardcoded stuff with html

    $(document).trigger('html:generated', html);

    return html;
}

$(document).on('html:generating', function(e, html) {
    html = '<span>' + html + '</span>';
});

$(document).on('html:generated', function(e, html) {
    console.log(html);  // prints <b>John Doe</b>
                        // expected <span><b>John Doe</b></span>
});

generateHTML();

这在处理 Mustache(或任何其他模板库)动态 html 代码时非常有用。

您可能想了解闭包的工作原理。 (所有 javascript 个函数都是闭包)

对于这个特定的问题,您所要做的就是将 html 变量的声明移到函数之外,移到更高的范围。然后,如果您仍想在事件处理程序中传递变量,则需要使用不同的名称。

var outerHtml = '';
function generateHTML() {    
    // Some html generating code
    outerHtml += '<b>John Doe</b>';

    $(document).trigger('html:generating', html);

    // Do more hardcoded stuff with html

    $(document).trigger('html:generated', html);

    return outerHtml;
}

$(document).on('html:generating', function(e, html) {
    outerHtml = '<span>' + html + '</span>';
});

$(document).on('html:generated', function(e, html) {
    console.log(outerHtml);  // prints <b>John Doe</b>
                        // expected <span><b>John Doe</b></span>
});

generateHTML();

如果您正在谈论通过引用传递 html,有一种方法可以做到。作为函数参数传递的所有内容都是按值传递的,但是如果传递一个对象,对象属性仍然指向原始值,因为指针被复制了。所以,你可以这样做:

function generateHTML()
{
    var container={html: ''};

    // Some html generating code
    container.html += '<b>John Doe</b>';

    $(document).trigger('html:generating', container);

    // Do more hardcoded stuff with html

    $(document).trigger('html:generated', container);

    return container.html;
}

$(document).on('html:generating', function(e, container) {
    container.html = '<span>' + container.html + '</span>';
});

$(document).on('html:generated', function(e, container) {
    console.log(container.html);
});

generateHTML();

您可以将变量移动到更高的范围(如@potter 所建议的)。如果您创建一个对象,可能会更容易使用,但如果您执行的是非常简单的任务,则可能没有必要。

理想情况下,'Renderer' 代码将在其自己的文件中以供重复使用。

有关基本示例,请参阅下面的代码变体。

// Some Object
var Renderer = function(scope, args) {
 var self = this;
  var scope = $(scope) || $(document);
  var html = args.html || "";
  
  self.setHtml = function(setHtml){
   html = setHtml;
  }
  
  self.getHtml = function(){
   return html || "";
  }
  
  self.generateHTML = function() {
    scope.trigger('html:generating', self.getHtml());

    // Do more hardcoded stuff with html
  
    scope.trigger('html:generated', self.getHtml());
  }
  return self;
}


// Your Code
var contentScope = document;
var contentRenderer = new Renderer(contentScope, {html: "<b>John Doe</b>"});

$(contentScope).on('html:generating', function(e, html) {
    contentRenderer.setHtml('<span>' + html + '</span>');
});

$(contentScope).on('html:generated', function(e, html) {
    console.log(html);  // prints <b>John Doe</b>
                        // expected <span><b>John Doe</b></span>
});

contentRenderer.generateHTML();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>