我应该将功能块封装在匿名 JavaScript 函数中吗?
我的直觉是,将代码块封装在匿名函数中是个好主意,如下所示:
(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();
操作是否一定会一直保留,直到它超出范围?或者口译员能否立即告知何时不再需要?
更好的例子
我还想澄清一下,我不一定在谈论全局范围。考虑一个看起来像的块
(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.
})();
我的假设和结论正确吗?每当我不打算重用一个块时,我不仅应该将其封装在函数中,而且应该将其封装在匿名函数中,这样该函数就没有引用并且在调用后被删除,对吗?
My intuition is that it's a good idea to encapsulate blocks of code in anonymous functions like this:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
Because I'm not going to need aVar
again, so I assume that the garbage collector will then delete aVar
when it goes out of scope. Is this right? Or are interpreters smart enough to see that I don't use the variable again and clean it up immediately? Are there any reasons such as style or readability that I should not use anonymous functions this way?
Also, if I name the function, like this:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
does operations
then necessarily stick around until it goes out of scope? Or can the interpreter immediately tell when it's no longer needed?
A Better Example
I'd also like to clarify that I'm not necessarily talking about global scope. Consider a block that looks like
(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.
})();
Are my assumptions and conclusions in there correct? Whenever I'm not going to reuse a block, I should not only encapsulate it in a function, but encapsulate it in an anonymous function so that the function has no references and is deleted after it's called, right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你是对的,将变量粘贴在匿名函数中是避免弄乱全局对象的好习惯。
回答你的后两个问题:解释器完全不可能知道只要有一个全局可见的引用,一个对象就不会被再次使用。据解释器所知,您可以随时评估一些依赖于
window['aVar']
或window['operation']
的代码。本质上,请记住两件事:
window
)。总而言之,这些意味着全局变量中的对象在脚本的生命周期内持续存在(除非重新分配变量)。这就是我们声明匿名函数的原因——变量获得一个新的上下文对象,该对象在函数完成执行后立即消失。除了提高效率之外,它还减少了名称冲突的机会。
不过,您的第二个示例(使用内部匿名函数)可能有点过于热心。我不会担心那里“帮助垃圾收集器”——GC 可能不会在该函数中间运行。担心那些会持续保留的东西,而不仅仅是比原本保留的时间稍长一些。这些自动执行的匿名函数基本上是自然归属在一起的代码模块,因此一个好的指南是考虑这是否描述了您正在做的事情。
不过,在匿名函数中使用匿名函数是有原因的。例如,在本例中:
这会导致点击回调捕获该巨大的数组,使其永远不会消失。您可以通过在其自己的函数内隔离数组来避免这种情况。
You're right that sticking variables inside an anonymous function is a good practice to avoid cluttering up the global object.
To answer your latter two questions: It's completely impossible for the interpreter to know that an object won't be used again as long as there's a globally visible reference to it. For all the interpreter knows, you could eval some code that depends on
window['aVar']
orwindow['operation']
at any moment.Essentially, remember two things:
window
in client-side Javascript).Combined, these mean that objects in global variables last for the lifetime of your script (unless the variable is reassigned). This is why we declare anonymous functions — the variables get a new context object that disappears as soon as the function finishes execution. In addition to the efficiency wins, it also reduces the chance of name collisions.
Your second example (with the inner anonymous function) might be a little overzealous, though. I wouldn't worry about "helping the garbage collector" there — GC probably isn't going to run in the middle that function anyway. Worry about things that will be kept around persistently, not just slightly longer than they otherwise would be. These self-executing anonymous functions are basically modules of code that naturally belong together, so a good guide is to think about whether that describes what you're doing.
There are reasons to use anonymous functions inside anonymous functions, though. For example, in this case:
This results in that gigantic array being captured by the click callback so that it never goes away. You could avoid this by quarantining the array inside its own function.
您添加到全局范围的任何内容都将保留在那里,直到页面被卸载(除非您专门删除它)。
通常,最好将属于一起的变量和函数放在本地作用域或对象中,以便它们尽可能少地添加到全局命名空间中。这样,重用代码就容易多了,因为您可以在页面中组合不同的脚本,同时将命名冲突的风险降至最低。
Anything that you add to the global scope will stay there until the page is unloaded (unless you specifically remove it).
It's generally a good idea to put variables and function that belong together either in a local scope or in an object, so that they add as little as possible to the global namespace. That way it's a lot easier to reuse code, as you can combine different scripts in a page with minimal risks for naming collisions.