问题
This function works:
function refreshCodeMirror(){
$("textarea").each(function(){
var codeMirror = $(this).data('codeMirror');
setTimeout(function(codeMirror){
return function () {
codeMirror.refresh();
}
}(codeMirror), 10)
});
}
But when I tried to simplify it to this:
function refreshCodeMirror(){
$("textarea").each(function(){
var codeMirror = $(this).data('codeMirror');
setTimeout(codeMirror.refresh, 10)
});
}
The simplification does not work.
Some (possibly irrelevant) context:
The refreshCodeMirror function is being called in the onclick for a bootstrap tab-header within a django template:
<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>
Everything works fine with the first function above and, while I would like to remove all the redundant refresh calls, they don't seem to matter and when I use a single text area (by passing the element id), the working function above stops working.
回答1:
The problem is you lose the context.
Functions which are not called directly on an object and are not manually bound to a context, are called in the global context.
var obj = {
print: function() {
document.write('<pre>' + this + '</pre>');
}
};
obj.print();
var p = obj.print;
p();
When you use setTimeout
or other similar functions, it's like doing this:
function setTimeout(f, time) {
wait(time);
f();
}
So your refresh
function is expecting this
to be equal to your codeMirror
instance but instead it's equal to the window
or undefined
(depending on if you're in strict mode).
There are a few ways to fix this. One is to pass a new function to setTimeout
where you call your original function.
setTimeout(function() {
codeMirror.refresh();
}, 10);
Another way, it to use bind to pass it a copy of the function with this
set to the correct object.
setTimeout(codeMirror.refresh.bind(codeMirror), 10);
来源:https://stackoverflow.com/questions/37262818/why-are-these-two-javascript-functions-not-equivalent