我可以命名一个 JavaScript 函数并立即执行它吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6404196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I name a JavaScript function and execute it immediately?
提问by Rudie
I have quite a few of these:
我有很多这样的:
function addEventsAndStuff() {
// bla bla
}
addEventsAndStuff();
function sendStuffToServer() {
// send stuff
// get HTML in response
// replace DOM
// add events:
addEventsAndStuff();
}
Re-adding the events is necessary because the DOM has changed, so previously attached events are gone. Since they have to be attached initially as well (duh), they're in a nice function to be DRY.
重新添加事件是必要的,因为 DOM 已更改,因此先前附加的事件已消失。由于它们最初也必须连接(duh),因此它们具有很好的 DRY 功能。
There's nothing wrong with this set up (or is there?), but can I smooth it a little bit? I'd like to create the addEventsAndStuff()
function and immediately call it, so it doesn't look so amateuristic.
这个设置没有问题(或者有没有问题?),但我可以稍微平滑一下吗?我想创建addEventsAndStuff()
函数并立即调用它,所以它看起来不那么业余。
Both following respond with a syntax error:
以下两个都响应语法错误:
function addEventsAndStuff() {
alert('oele');
}();
(function addEventsAndStuff() {
alert('oele');
})();
Any takers?
有接班人吗?
回答by Mark Kahn
There's nothing wrong with the example you posted in your question.. The other way of doing it may look odd, but:
您在问题中发布的示例没有任何问题。另一种做法可能看起来很奇怪,但是:
var addEventsAndStuff;
(addEventsAndStuff = function(){
// add events, and ... stuff
})();
There are two ways to define a function in JavaScript. A function declaration:
在 JavaScript 中有两种定义函数的方法。一个函数声明:
function foo(){ ... }
and a function expression, which is anyway of defining a function other than the above:
和一个函数表达式,它是定义除上述以外的函数的任何方式:
var foo = function(){};
(function(){})();
var foo = {bar : function(){}};
...etc
...等等
function expressions can be named, but their name is not propagated to the containing scope. Meaning this code is valid:
函数表达式可以命名,但它们的名称不会传播到包含范围。这意味着此代码有效:
(function foo(){
foo(); // recursion for some reason
}());
but this isn't:
但这不是:
(function foo(){
...
}());
foo(); // foo does not exist
So in order to name your function and immediately call it, you need to define a local variable, assign your function to it as an expression, then call it.
因此,为了命名您的函数并立即调用它,您需要定义一个局部变量,将您的函数作为表达式分配给它,然后调用它。
回答by James Gorrie
There is a good shorthand to this (not needing to declare any variables bar the assignment of the function):
对此有一个很好的简写(不需要声明任何变量来阻止函数的分配):
var func = (function f(a) { console.log(a); return f; })('Blammo')
回答by T.J. Crowder
There's nothing wrong with this set up (or is there?), but can I smooth it a little bit?
这个设置没有问题(或者有没有问题?),但我可以稍微平滑一下吗?
Look at using event delegation instead. That's where you actually watch for the event on a container that doesn'tgo away, and then use event.target
(or event.srcElement
on IE) to figure out where the event actually occurred and handle it correctly.
请考虑使用事件委托。这就是您实际在不会消失的容器上观察事件的地方,然后使用event.target
(或event.srcElement
在 IE 上)找出事件实际发生的位置并正确处理它。
That way, you only attach the handler(s) once, and they just keep working even when you swap out content.
这样,您只需附加一次处理程序,即使您换出内容,它们也会继续工作。
Here's an example of event delegation without using any helper libs:
这是一个不使用任何帮助库的事件委托示例:
(function() {
var handlers = {};
if (document.body.addEventListener) {
document.body.addEventListener('click', handleBodyClick, false);
}
else if (document.body.attachEvent) {
document.body.attachEvent('onclick', handleBodyClick);
}
else {
document.body.onclick = handleBodyClick;
}
handlers.button1 = function() {
display("Button One clicked");
return false;
};
handlers.button2 = function() {
display("Button Two clicked");
return false;
};
handlers.outerDiv = function() {
display("Outer div clicked");
return false;
};
handlers.innerDiv1 = function() {
display("Inner div 1 clicked, not cancelling event");
};
handlers.innerDiv2 = function() {
display("Inner div 2 clicked, cancelling event");
return false;
};
function handleBodyClick(event) {
var target, handler;
event = event || window.event;
target = event.target || event.srcElement;
while (target && target !== this) {
if (target.id) {
handler = handlers[target.id];
if (handler) {
if (handler.call(this, event) === false) {
if (event.preventDefault) {
event.preventDefault();
}
return false;
}
}
}
else if (target.tagName === "P") {
display("You clicked the message '" + target.innerHTML + "'");
}
target = target.parentNode;
}
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
})();
Note how if you click the messages that get dynamically added to the page, your click gets registered and handled even though there's no code to hook events on the new paragraphs being added. Also note how your handlers are just entries in a map, and you have onehandler on the document.body
that does all the dispatching. Now, you probably root this in something more targeted than document.body
, but you get the idea. Also, in the above we're basically dispatching by id
, but you can do matching as complex or simple as you like.
请注意,如果您单击动态添加到页面的消息,即使没有代码在添加的新段落上挂钩事件,您的单击也会被注册和处理。还要注意您的处理程序如何只是地图中的条目,并且您有一个处理程序document.body
来完成所有调度。现在,您可能将其根源于比 更有针对性的内容document.body
,但您明白了。此外,在上面我们基本上是通过 调度id
,但是您可以根据需要进行复杂或简单的匹配。
Modern JavaScript libraries like jQuery, Prototype, YUI, Closure, or any of several othersshould offer event delegation features to smooth over browser differences and handle edge cases cleanly. jQuery certainly does, with both its live
and delegate
functions, which allow you to specify handlers using a full range of CSS3 selectors (and then some).
现代 JavaScript 库,如jQuery、Prototype、YUI、Closure或其他几个库中的任何一个都应该提供事件委托功能来平滑浏览器差异并干净地处理边缘情况。jQuery 当然可以,它的功能live
和delegate
功能都允许您使用全范围的 CSS3 选择器(以及一些)指定处理程序。
For example, here's the equivalent code using jQuery (except I'm sure jQuery handles edge cases the off-the-cuff raw version above doesn't):
例如,这里是使用 jQuery 的等效代码(除了我确定 jQuery 处理边缘情况,上面的现成原始版本没有):
(function($) {
$("#button1").live('click', function() {
display("Button One clicked");
return false;
});
$("#button2").live('click', function() {
display("Button Two clicked");
return false;
});
$("#outerDiv").live('click', function() {
display("Outer div clicked");
return false;
});
$("#innerDiv1").live('click', function() {
display("Inner div 1 clicked, not cancelling event");
});
$("#innerDiv2").live('click', function() {
display("Inner div 2 clicked, cancelling event");
return false;
});
$("p").live('click', function() {
display("You clicked the message '" + this.innerHTML + "'");
});
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
回答by pimvdb
You might want to create a helper function like this:
你可能想创建一个这样的辅助函数:
function defineAndRun(name, func) {
window[name] = func;
func();
}
defineAndRun('addEventsAndStuff', function() {
alert('oele');
});
回答by KooiInc
Your code contains a typo:
您的代码包含一个错字:
(function addEventsAndStuff() {
alert('oele');
)/*typo here, should be }*/)();
so
所以
(function addEventsAndStuff() {
alert('oele');
})();
works. Cheers!
作品。干杯!
[edit] based on comment: and this should run and return the function in one go:
[编辑]基于评论:这应该一次运行并返回函数:
var addEventsAndStuff = (
function(){
var addeventsandstuff = function(){
alert('oele');
};
addeventsandstuff();
return addeventsandstuff;
}()
);
回答by Alberto
Even simpler with ES6:
使用 ES6 更简单:
var result = ((a, b) => `${a} ${b}`)('Hello','World')
// result = "Hello World"
var result2 = (a => a*2)(5)
// result2 = 10
var result3 = (concat_two = (a, b) => `${a} ${b}`)('Hello','World')
// result3 = "Hello World"
concat_two("My name", "is Foo")
// "My name is Foo"
回答by Praveen Lobo
If you want to create a function and execute immediately -
如果你想创建一个函数并立即执行 -
// this will create as well as execute the function a()
(a=function a() {alert("test");})();
// this will execute the function a() i.e. alert("test")
a();
回答by Alexander Ruliov
Try to do like that:
尝试这样做:
var addEventsAndStuff = (function(){
var func = function(){
alert('ole!');
};
func();
return func;
})();