Mam kilka z nich:
function addEventsAndStuff() {
// bla bla
}
addEventsAndStuff();
function sendStuffToServer() {
// send stuff
// get HTML in response
// replace DOM
// add events:
addEventsAndStuff();
}
Ponowne dodanie wydarzeń jest konieczne, ponieważ DOM się zmienił, więc wcześniej dołączone zdarzenia zniknęły. Ponieważ muszą być również przymocowane na początku (duh), są w fajnej funkcji, aby być SUCHE.
Nie ma nic złego w tej konfiguracji (czy jest?), Ale czy mogę trochę wygładzić? Chciałbym stworzyć addEventsAndStuff()
funkcję i od razu ją nazwać, żeby nie wyglądała tak amatorsko.
Oba poniższe odpowiedzi odpowiadają błędem składni:
function addEventsAndStuff() {
alert('oele');
}();
(function addEventsAndStuff() {
alert('oele');
})();
Jacyś chętni?
javascript
function
Rudie
źródło
źródło
Odpowiedzi:
Nie ma nic złego w przykładzie, który zamieściłeś w swoim pytaniu. Inna metoda może wyglądać dziwnie, ale:
var addEventsAndStuff; (addEventsAndStuff = function(){ // add events, and ... stuff })();
Istnieją dwa sposoby definiowania funkcji w JavaScript. Deklaracja funkcji:
function foo(){ ... }
oraz wyrażenie funkcyjne, które jest dowolnym sposobem zdefiniowania funkcji innej niż powyższe:
var foo = function(){}; (function(){})(); var foo = {bar : function(){}};
...itp
wyrażeniom funkcyjnym można nadawać nazwy, ale ich nazwa nie jest propagowana do zakresu zawierającego. Znaczenie tego kodu jest ważne:
(function foo(){ foo(); // recursion for some reason }());
ale to nie jest:
(function foo(){ ... }()); foo(); // foo does not exist
Aby więc nazwać swoją funkcję i natychmiast ją wywołać, musisz zdefiniować zmienną lokalną, przypisać jej funkcję jako wyrażenie, a następnie ją wywołać.
źródło
call()
metody z tego miejsca: stackoverflow.com/a/12359154/1231001Jest na to dobry skrót (nie trzeba deklarować żadnych zmiennych poza przypisaniem funkcji):
var func = (function f(a) { console.log(a); return f; })('Blammo')
źródło
r
funkcja zwróci? Czyfunction r
lubvar r
? Po prostu ciekawy. Dobre rozwiązanie. Nie musiał to być jednak jeden loc =)return r
byłby taki,function r
ponieważ był to jego zakres. Pisałem Scalę tak nieustannie, próbując znaleźć coś na linii.Zamiast tego spójrz na użycie delegowania zdarzeń. W tym miejscu faktycznie obserwujesz zdarzenie w kontenerze, który nie znika, a następnie używasz
event.target
(lubevent.srcElement
w IE), aby dowiedzieć się, gdzie zdarzenie faktycznie miało miejsce i poprawnie je obsłużyć.W ten sposób dołączasz moduły obsługi tylko raz, a one po prostu działają nawet po wymianie treści.
Oto przykład delegowania zdarzeń bez użycia bibliotek pomocniczych:
(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); } })();
Przykład na żywo
Zwróć uwagę, że jeśli klikniesz wiadomości, które są dynamicznie dodawane do strony, kliknięcie zostanie zarejestrowane i obsługiwane, nawet jeśli nie ma kodu, który przechwyciłby zdarzenia na dodawanych nowych akapitach. Zwróć również uwagę, że twoje programy obsługi są tylko wpisami na mapie, a masz jeden moduł obsługujący,
document.body
który wykonuje całą wysyłkę. Prawdopodobnie zakorzenisz to w czymś bardziej ukierunkowanym niżdocument.body
, ale masz pomysł. Ponadto w powyższym zasadniczo wysyłamyid
, ale możesz dopasować tak złożone lub proste, jak chcesz.Nowoczesne biblioteki JavaScript, takie jak jQuery , Prototype , YUI , Closure lub dowolne inne, powinny oferować funkcje delegowania zdarzeń, aby wygładzić różnice w przeglądarkach i czysto obsługiwać skrajne przypadki. jQuery z pewnością to robi, zarówno z jego funkcjami, jak
live
idelegate
, które pozwalają określić moduły obsługi przy użyciu pełnego zakresu selektorów CSS3 (a także niektórych).Na przykład, oto równoważny kod używający jQuery (z wyjątkiem tego, że jestem pewien, że jQuery obsługuje przypadki krawędziowe, które nie są dostępne w surowej wersji powyżej):
(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);
Kopia na żywo
źródło
Event.target
, ponieważ to nie zawsze jest właściwy cel. Zgadza się. Jeśli kliknieszIMG
wewnątrz a,DIV
aDIV
ma zdarzenie,Event.target
zostanie wyświetloneIMG
i nie ma sposobu, abyDIV
ładnie uzyskać obiekt. edytuj Btw I hate jQuery's.live
'event'event.target
: To, co opisujesz, nie jest złe, jest poprawne. Jeśli kliknieszimg
wewnątrz adiv
i oglądaszdiv
,event.target
to jestimg
(ithis
jestdiv
). Spójrz ponownie na powyższe. Możesz dołączyć moduł obsługi w dowolnym punkcie łańcucha między klikniętym elementem (img
na przykład) a elementem, który obserwujesz (powyżej, na samym doledocument.body
). Relive
: Zdecydowanie wolędelegate
, bardziej zamkniętą wersjęlive
. Użyłemlive
powyżej, ponieważ było to najbliższe temu, co zrobiłem w surowym przykładzie. PozdrawiamMożesz chcieć utworzyć taką funkcję pomocniczą:
function defineAndRun(name, func) { window[name] = func; func(); } defineAndRun('addEventsAndStuff', function() { alert('oele'); });
źródło
Twój kod zawiera literówkę:
(function addEventsAndStuff() { alert('oele'); )/*typo here, should be }*/)();
więc
(function addEventsAndStuff() { alert('oele'); })();
Pracuje. Twoje zdrowie!
[ edytuj ] na podstawie komentarza: a to powinno uruchomić i zwrócić funkcję za jednym razem:
var addEventsAndStuff = ( function(){ var addeventsandstuff = function(){ alert('oele'); }; addeventsandstuff(); return addeventsandstuff; }() );
źródło
ReferenceError
Jeszcze prostsze z 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"
źródło
concat_two
działa idealnie, ALE zawsze definiuje to w zakresie globalnym, więc nie będzie działać"use strict"
. To nie jest dla mnie ważne, ale to mały minus.Jeśli chcesz utworzyć funkcję i wykonać ją natychmiast -
// 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();
źródło
Spróbuj zrobić tak:
var addEventsAndStuff = (function(){ var func = function(){ alert('ole!'); }; func(); return func; })();
źródło
var foo = (function() {...})();
wywołuje funkcję przed przypisaniem. Nawias musi zawierać przypisanie. (Chcesz przydzielić, a następnie zadzwoń.)