Tengo bastantes de estos:
function addEventsAndStuff() {
// bla bla
}
addEventsAndStuff();
function sendStuffToServer() {
// send stuff
// get HTML in response
// replace DOM
// add events:
addEventsAndStuff();
}
Es necesario volver a agregar los eventos porque el DOM ha cambiado, por lo que los eventos adjuntos anteriormente se han ido. Como también tienen que estar conectados inicialmente (duh), están en una buena función para estar SECOS.
No hay nada de malo en esta configuración (¿o no?), Pero ¿puedo suavizarlo un poco? Me gustaría crear la addEventsAndStuff()
función y llamarla inmediatamente, para que no parezca tan amateur.
Ambos siguientes responden con un error de sintaxis:
function addEventsAndStuff() {
alert('oele');
}();
(function addEventsAndStuff() {
alert('oele');
})();
¿Ningún arrendatario?
javascript
function
Rudie
fuente
fuente
Respuestas:
No hay nada de malo en el ejemplo que publicó en su pregunta. La otra forma de hacerlo puede parecer extraña, pero:
var addEventsAndStuff; (addEventsAndStuff = function(){ // add events, and ... stuff })();
Hay dos formas de definir una función en JavaScript. Una declaración de función:
function foo(){ ... }
y una expresión de función, que es cualquier forma de definir una función distinta a la anterior:
var foo = function(){}; (function(){})(); var foo = {bar : function(){}};
... etc
Se pueden nombrar expresiones de función, pero su nombre no se propaga al ámbito contenedor. Lo que significa que este código es válido:
(function foo(){ foo(); // recursion for some reason }());
pero esto no es:
(function foo(){ ... }()); foo(); // foo does not exist
Entonces, para nombrar su función e inmediatamente llamarla, necesita definir una variable local, asignarle su función como una expresión y luego llamarla.
fuente
call()
método desde aquí: stackoverflow.com/a/12359154/1231001Hay una buena abreviatura para esto (no es necesario declarar ninguna variable que excluya la asignación de la función):
var func = (function f(a) { console.log(a); return f; })('Blammo')
fuente
r
devolverá la función? ¿Elfunction r
o elvar r
? Sólo curioso. Buena solución. Aunque no tenía que ser una locomotora =)return r
habría sido elfunction r
ya que ese era su alcance. He estado escribiendo Scala permanentemente tratando de poner algo en línea.En su lugar, considere usar la delegación de eventos. Ahí es donde realmente observa el evento en un contenedor que no desaparece, y luego usa
event.target
(oevent.srcElement
en IE) para averiguar dónde ocurrió realmente el evento y manejarlo correctamente.De esa manera, solo adjunta los controladores una vez y seguirán funcionando incluso cuando intercambie contenido.
A continuación, se muestra un ejemplo de delegación de eventos sin utilizar ninguna biblioteca auxiliar:
(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); } })();
Ejemplo vivo
Tenga en cuenta que si hace clic en los mensajes que se agregan dinámicamente a la página, su clic se registra y se maneja a pesar de que no hay código para enganchar eventos en los nuevos párrafos que se agregan. También tenga en cuenta que sus controladores son solo entradas en un mapa, y tiene un controlador en el
document.body
que realiza todo el envío. Ahora, probablemente arraigue esto en algo más específico quedocument.body
, pero ya entiende la idea. Además, en lo anterior básicamente estamos enviando porid
, pero puede hacer una coincidencia tan compleja o simple como desee.Las bibliotecas de JavaScript modernas como jQuery , Prototype , YUI , Closure o cualquiera de varias otras deberían ofrecer funciones de delegación de eventos para suavizar las diferencias del navegador y manejar los casos extremos de manera limpia. jQuery ciertamente lo hace, con sus funciones
live
ydelegate
, que le permiten especificar controladores usando una gama completa de selectores CSS3 (y más).Por ejemplo, aquí está el código equivalente usando jQuery (excepto que estoy seguro de que jQuery maneja casos extremos que la versión sin procesar de arriba no lo hace):
(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);
Copia en vivo
fuente
Event.target
, porque ese no siempre es el objetivo correcto. Así es. Si hace clic en unIMG
dentro de aDIV
yDIV
tiene el evento,Event.target
será elIMG
y no hay forma de obtener elDIV
objeto correctamente. editar Por cierto, odio el.live
'evento' de jQueryevent.target
: Lo que describe no está mal, es correcto. Si hace clic en unimg
dentro de adiv
y está viendo eldiv
,event.target
es elimg
(ythis
es eldiv
). Eche otro vistazo a lo anterior. Puede adjuntar un controlador en cualquier punto de la cadena entre el elemento en el que se hizo clic (elimg
, por ejemplo) y el elemento que está viendo (en el de arriba, hasta abajodocument.body
). Relive
: Prefiero muchodelegate
, la versión más contenida delive
. Usélive
arriba porque era lo más cercano a lo que había hecho en el ejemplo en bruto. Mejor,Es posible que desee crear una función auxiliar como esta:
function defineAndRun(name, func) { window[name] = func; func(); } defineAndRun('addEventsAndStuff', function() { alert('oele'); });
fuente
Su código contiene un error tipográfico:
(function addEventsAndStuff() { alert('oele'); )/*typo here, should be }*/)();
entonces
(function addEventsAndStuff() { alert('oele'); })();
trabajos. ¡Salud!
[ editar ] basado en el comentario: y esto debería ejecutar y devolver la función de una sola vez:
var addEventsAndStuff = ( function(){ var addeventsandstuff = function(){ alert('oele'); }; addeventsandstuff(); return addeventsandstuff; }() );
fuente
ReferenceError
Aún más simple con 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"
fuente
concat_two
funciona perfectamente, PERO siempre lo define en el ámbito global, por lo que no funcionará con"use strict"
. Eso no es importante para mí, pero es un pequeño inconveniente.Si desea crear una función y ejecutarla inmediatamente:
// 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();
fuente
Intenta hacer así:
var addEventsAndStuff = (function(){ var func = function(){ alert('ole!'); }; func(); return func; })();
fuente
var foo = (function() {...})();
llama a la función antes de la asignación. El paréntesis debe incluir la tarea. (Desea asignar y luego llamar.)