为什么这两个javascript函数不相同?

Pau*_*ipp 0 javascript django jquery codemirror twitter-bootstrap

这个功能有效:

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

  });
}
Run Code Online (Sandbox Code Playgroud)

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

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

  });
}
Run Code Online (Sandbox Code Playgroud)

简化不起作用.

一些(可能不相关)背景:

在onclick中为django模板中的bootstrap tab-header调用了refreshCodeMirror函数:

   <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>
Run Code Online (Sandbox Code Playgroud)

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

Mik*_*uck 6

问题是你失去了背景.

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

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

obj.print();
var p = obj.print;
p();
Run Code Online (Sandbox Code Playgroud)

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

function setTimeout(f, time) {
  wait(time);
  f();
}
Run Code Online (Sandbox Code Playgroud)

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

有几种方法可以解决这个问题.一种是将新功能传递给setTimeout您调用原始功能的位置.

setTimeout(function() {
  codeMirror.refresh();
}, 10);
Run Code Online (Sandbox Code Playgroud)

另一种方式,它用于bind将设置的函数副本传递this给正确的对象.

setTimeout(codeMirror.refresh.bind(codeMirror), 10);
Run Code Online (Sandbox Code Playgroud)