JSlint错误';Don';t在循环中生成函数;这就引出了关于Javascript本身的问题
我有一些在循环中调用匿名函数的代码,类似于下面的伪示例:JSlint错误';Don';t在循环中生成函数;这就引出了关于Javascript本身的问题,javascript,jslint,Javascript,Jslint,我有一些在循环中调用匿名函数的代码,类似于下面的伪示例: for (i = 0; i < numCards; i = i + 1) { card = $('<div>').bind('isPopulated', function (ev) { var card = $(ev.currentTarget); .... (i=0;i
for (i = 0; i < numCards; i = i + 1) {
card = $('<div>').bind('isPopulated', function (ev) {
var card = $(ev.currentTarget);
....
(i=0;i{
卡=$('').bind('isPopulated',函数(ev){
var卡=$(ev.currentTarget);
....
JSLint报告错误“不要在循环中生成函数”。我喜欢保持代码JSLint干净。我知道我可以将匿名函数移出循环,并将其作为命名函数调用。除此之外,我的问题是:
Javascript解释器真的会在每次迭代中创建一个函数实例吗?还是真的只有一个函数实例“已编译”,并且重复执行相同的代码?也就是说,JSLint“建议”将函数移出循环实际上会影响代码的效率?解释器可能会在每次迭代中实际创建一个新的函数对象,这仅仅是因为该函数可能是一个闭包,需要捕获其外部范围内任何变量的当前值
这就是为什么
JSLint
想吓唬你不要在一个紧密的循环中创建许多匿名函数。部分取决于你是在使用函数表达式还是函数声明。它们是不同的东西,发生在不同的时间,对周围的作用域有不同的影响。所以让我们从h.区别
函数表达式是一种函数
产品,其中使用结果作为右值-例如,将结果指定给变量或属性,或将其作为参数传递给函数等。这些都是函数表达式:
(不要使用最后一个-称为命名函数表达式-实现有bug,)
相反,这是一个函数声明:
它是独立的,您没有将结果用作右侧值
它们之间的两个主要区别是:
function foo() {
for (i = 0; i < limit; ++i) {
function bar() { ... } // <== Don't do this
bar();
}
}
函数foo(){
对于(i=0;i function bar(){…}//Boo to JSLint。它就像头上的钝器。每次遇到函数
时都会创建一个新的函数对象(它是一个语句/表达式,而不是声明--编辑:这是一个善意的谎言。请参见T.J.Crowders的答案)通常这是在一个闭包循环中完成的。更大的问题是创建错误的闭包
例如:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
alert(i)
}, 10)
}
for(变量i=0;i<10;i++){
setTimeout(函数(){
警报(一)
}, 10)
}
这不是“在循环中创建函数,甚至不理解JS用于变量作用域和闭包的规则”(变量不绑定在闭包中,作用域——执行上下文——是)的问题
但是,您可能希望在函数中创建一个闭包。请考虑这个不太令人惊讶的代码:
for (var i = 0; i < 10; i++) {
setTimeout((function (_i) {
return function () {
alert(_i)
}
})(i), 10)
}
for(变量i=0;i<10;i++){
setTimeout((函数(_i){
返回函数(){
警报(_i)
}
})(i) ,10)
}
哦,不!我还是创建了一个函数
Javascript解释器真的会在每次迭代中创建函数的实例吗
它必须这样做,因为它不知道函数对象是否会在其他地方被修改。请记住,函数是标准JavaScript对象,因此它们可以具有与任何其他对象一样的属性。执行此操作时:
card = $('<div>').bind('isPopulated', function (ev) { ... })
显然,如果在所有迭代中共享函数对象,这将导致错误的行为。
@ CasabaChana:如果在规范中读取语法,则是无效的。考虑条件句:特别重要的是:<代码>(a){函数英尺(){{}}} {函数FULL(){{}}。
。这就是为什么如果你阅读语法,它是无效的;-)对不起,我刚刚检查了规范,你是对的。但在我看来,如果语法允许,它的行为方式将与如果(a){var b;}否则{var c;}
与函数开始时声明的内容相同。@T.J.Crowder:你说得对,我刚刚检查了规范。FunctionBody
包含SourceElements
,其中包含SourceElement
s,其中既包含语句
s又包含FunctionDeclaration
s@MKSafi: 不,我没有忘记这一点。第一个循环中有一个声明,它是无效的JavaScript(目前)。那里根本不允许有声明。是的,在上一个例子中,bar
函数是在循环之前创建的——这就是我在那里的目的,我说(实际上)“我会这样做的。”。重新表达式与声明:如果它用作右边值(例如,赋值或初始化的右边,或传递到函数的右边,或前面有运算符),则它是一个表达式。如果不是,则它是一个声明。@MKSafi:right.And of c
for (var i = 0; i < 10; i++) {
setTimeout(function () {
alert(i)
}, 10)
}
for (var i = 0; i < 10; i++) {
setTimeout((function (_i) {
return function () {
alert(_i)
}
})(i), 10)
}
card = $('<div>').bind('isPopulated', function (ev) { ... })
function bind(str, fn) {
fn.foo = str;
}