草庐IT

Javascript 函数作用域循环

coder 2025-01-13 原文

Here's an example一个简单的 JS 循环没有按预期运行的情况,因为循环变量不在单独的范围内。

通常提出的解决方案是构造一段看起来不愉快的循环代码,如下所示:

for (var i in obj) {
    (function() {
        ... obj[i] ... 
        // this new shadowed i here is now no longer getting changed by for loop
    })(i);
}

我的问题是,这可以改进吗?我可以用这个吗:

Object.prototype.each = function (f) {
    for (var i in this) {
        f(i,this[i]);
    }
};

// leading to this somewhat more straightforward invocation
obj.each(
    function(i,v) {
        ... v ...
        // alternatively, v is identical to
        ... obj[i] ...
    }
);

当我确定我需要一个“作用域循环”时?它看起来更干净一些,并且应该具有与常规 for 循环相似的性能(因为它以相同的方式使用)。

更新:似乎使用 Object.prototype 做事是一个巨大的禁忌,因为它几乎破坏了一切

这是一个侵入性较小的实现:

function each (obj,f) {
    for (var i in obj) {
        f(i,obj[i]);
    }
}

调用略微更改为

each(obj,
    function(i,v) {
        ... v ...
    }
);

所以我想我已经回答了我自己的问题,如果 jQuery 这样做,就不会出错。我忽略的任何问题都需要一个答案。

最佳答案

你的回答几乎涵盖了它,但我认为你的原始循环的变化值得注意,因为当 each() 函数不方便时,使用普通的 for 循环是合理的,无论出于何种原因。

更新:更改为使用类似于 example referenced by the question 的示例比较不同的方法。该示例必须进行调整,因为 each() 函数需要一个填充的数组来迭代。

假设以下设置:

var vals = ['a', 'b', 'c', 'd'],
    max = vals.length,
    closures = [],
    i;

使用问题中的示例,原始循环最终创建了 2n 个函数(其中 n 是迭代次数),因为在每次迭代期间创建了两个函数:

for (i = 0; i < max; i++) {
    closures[i] = (function(idx, val) {  // 1st - factoryFn - captures the values as arguments 
        return function() {              // 2nd - alertFn   - uses the arguments instead
            alert(idx + ' -> ' + val);   //                   of the variables
        };
    })(i, vals[i]);
}

这可以减少到只创建 n + 1 个函数,方法是在循环开始之前创建一次工厂函数,然后重新使用它:

var factoryFn = function(idx, val) {
    return function() {
        alert(idx + ' -> ' + val);
    };
};

for (i = 0; i < max; i++) {
    closures[i] = factoryFn(i, vals[i]); 
}

这几乎等同于 each() 函数在这种情况下的使用方式,这也会导致总共创建 n + 1 个函数。工厂函数创建一次并立即作为参数传递给 each()

each(vals, function(idx, val) {
    closures[idx] = function() {
        alert(idx + ' -> ' + val);
    };
});

FWIW,我认为使用 each() 的一个好处是代码更短一些,并且在传递到 each() 函数时可以正确创建工厂函数清楚地说明这是它的唯一用途。 for 循环版本的一个好处,IMO,是执行循环的代码就在那里,所以它的性质和行为是完全透明的,而 each() 函数可能是在不同的文件中定义,由其他人编写等。

关于Javascript 函数作用域循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14108230/

有关Javascript 函数作用域循环的更多相关文章

  1. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  5. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  6. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  9. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  10. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

随机推荐