【问题标题】:Why are these two javascript functions not equivalent?为什么这两个 javascript 函数不等价?
【发布时间】:2016-09-12 18:26:20
【问题描述】:

此功能有效:

function refreshCodeMirror(){
  $("textarea").each(function(){
    var codeMirror = $(this).data('codeMirror');
    setTimeout(function(codeMirror){
      return function () {
        codeMirror.refresh();
      }
    }(codeMirror), 10)

  });
}

但是当我试图将其简化为:

function refreshCodeMirror(){
  $("textarea").each(function(){
    var codeMirror = $(this).data('codeMirror');
    setTimeout(codeMirror.refresh, 10)

  });
}

简化不起作用。

一些(可能不相关的)上下文:

正在 onclick 中调用 refreshCodeMirror 函数以获取 django 模板中的引导选项卡标题:

   <div class="row">
        <div class="col-md-12">
            <ul class="nav nav-tabs" role="tablist">
                {% for field in form_tab_fields %}
                    <li role="presentation"{% if forloop.first %} class="active"{% endif %}>
                        <a class="tab-header" href="#{{ field.id_for_label }}_tab" data-toggle="tab" onclick="refreshCodeMirror()">{{ field.label_tag }}</a>
                    </li>
                {% endfor %}
            </ul>
            <div class="tab-content">
                {% for field in form_tab_fields %}
                    <div role="tabpanel"
                         class="form-group tab-pane{% if forloop.first %} active{% endif %}"
                         id="{{ field.id_for_label }}_tab">
                            {{ field }}
                    {{ field.errors }}
                    </div>
                {% endfor %}
            </div>
        </div>
    </div>

上面的第一个函数一切正常,虽然我想删除所有多余的刷新调用,但它们似乎并不重要,当我使用单个文本区域(通过传递元素 id)时,工作上面的函数停止工作。

【问题讨论】:

标签: javascript jquery django twitter-bootstrap codemirror


【解决方案1】:

问题是你失去了上下文。

未直接在对象上调用且未手动绑定到上下文的函数在全局上下文中调用。

var obj = {
  print: function() {
    document.write('<pre>' + this + '</pre>');
  }
};

obj.print();
var p = obj.print;
p();

当你使用setTimeout或其他类似功能时,就像这样做:

function setTimeout(f, time) {
  wait(time);
  f();
}

因此,您的 refresh 函数期望 this 等于您的 codeMirror 实例,但实际上它等于 windowundefined(取决于您是否处于严格模式)。

有几种方法可以解决此问题。一种是将新函数传递给setTimeout,您将在其中调用原始函数。

setTimeout(function() {
  codeMirror.refresh();
}, 10);

另一种方式,它使用bindthis 设置为正确对象的函数副本传递给它。

setTimeout(codeMirror.refresh.bind(codeMirror), 10);

【讨论】:

  • 传递“新”功能是我在问题的工作解决方案中所做的,不是吗?绑定似乎在重复某些事情,因为该函数已经绑定到 codeMirror 实例,但我从您方便的文档链接中看到绑定不是这种情况,谢谢!
  • setTimout(codeMirror.refresh.bind(codeMirror), 10) 解决方案不起作用:(
  • @PaulWhipp 那么您可能需要该原始函数参考。如果没有更好地描述问题,就不可能说。无论哪种方式,第一个解决方案都将始终有效。
  • 谢谢,是的 - CodeMirror 中的某些东西似乎使这一点变得必不可少。
猜你喜欢
  • 2011-03-18
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-14
  • 2018-01-21
  • 2023-04-05
  • 1970-01-01
相关资源
最近更新 更多