我的直觉是将代码块封装在像这样的匿名函数中是个好主意:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
因为我不再需要 aVar,所以我假设垃圾收集器将在超出范围时删除 aVar。这是正确的吗?或者解释器是否足够聪明,可以看到我不再使用该变量并立即清理它?是否有任何理由,例如风格或可读性,我应该不以这种方式使用匿名函数?
另外,如果我给函数命名,像这样:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
operations 是否一定会一直存在直到超出范围?还是解释器可以立即告诉您何时不再需要它?
我还想澄清一下,我不一定在谈论全局范围。考虑一个看起来像的 block
(function() {
var date = new Date(); // I want to keep this around indefinitely
// And even thought date is private, it will be accessible via this HTML node
// to other scripts.
document.getElementById('someNode').date = date;
// This function is private
function someFunction() {
var someFuncMember;
}
// I can still call this because I named it. someFunction remains available.
// It has a someFuncMember that is instantiated whenever someFunction is
// called, but then goes out of scope and is deleted.
someFunction();
// This function is anonymous, and its members should go out of scope and be
// deleted
(function() {
var member;
})(); // member is immediately deleted
// ...and the function is also deleted, right? Because I never assigned it to a
// variable. So for performance, this is preferrable to the someFunction
// example as long as I don't need to call the code again.
})();
我的假设和结论是否正确?每当我不打算重用一个 block 时,我不仅应该把它封装在一个函数中,而是应该把它封装在一个匿名函数中,这样函数就没有引用,调用后就被删除,对吧?
最佳答案
你说得对,在匿名函数中加入变量是避免弄乱全局对象的好习惯。
回答你的后两个问题:解释器完全不可能知道一个对象不会被再次使用,只要有一个全局可见的引用。解释器都知道,您可以随时评估一些依赖于 window['aVar'] 或 window['operation'] 的代码。
基本上,请记住两件事:
window)。结合起来,这些意味着全局变量中的对象在脚本的生命周期内持续存在(除非变量被重新分配)。这就是我们声明匿名函数的原因——变量获得一个新的上下文对象,该对象在函数完成执行后立即消失。除了效率取胜之外,它还减少了名称冲突的机会。
不过,您的第二个示例(带有内部匿名函数)可能有点过分热心。我不会担心在那里“帮助垃圾收集器”——GC 可能不会在该函数的中间运行。担心那些会持续存在的东西,而不仅仅是比它们原本会存在的时间稍微长一点。这些自执行的匿名函数基本上是自然属于一起的代码模块,因此一个很好的指导是考虑这是否描述了您正在做的事情。
不过,在匿名函数内部使用匿名函数是有原因的。例如,在这种情况下:
(function () {
var bfa = new Array(24 * 1024*1024);
var calculation = calculationFor(bfa);
$('.resultShowButton').click( function () {
var text = "Result is " + eval(calculation);
alert(text);
} );
})();
这导致巨大的数组被点击回调捕获,因此它永远不会消失。您可以通过将数组隔离在它自己的函数中来避免这种情况。
关于javascript - 我应该将功能 block 封装在匿名 JavaScript 函数中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3753619/
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您