JavaScript 함수의 이름을 지정하고 즉시 실행할 수 있습니까?
나는 이것들 중 꽤있다 :
function addEventsAndStuff() {
// bla bla
}
addEventsAndStuff();
function sendStuffToServer() {
// send stuff
// get HTML in response
// replace DOM
// add events:
addEventsAndStuff();
}
DOM이 변경 되었기 때문에 이벤트를 다시 추가해야하므로 이전에 첨부 된 이벤트가 사라집니다. 초기에도 부착해야하므로 (duh) DRY 기능이 좋다.
이 설정에는 문제가 없지만 (또는 존재합니까?) 조금 부드럽게 할 수 있습니까? addEventsAndStuff()
함수 를 만들고 즉시 호출하고 싶어서 그렇게 아마추어 적으로 보이지 않습니다.
다음 두 가지 모두 구문 오류로 응답합니다.
function addEventsAndStuff() {
alert('oele');
}();
(function addEventsAndStuff() {
alert('oele');
})();
수취인이 있습니까?
질문에 게시 한 예제에는 문제가 없습니다. 다른 방법은 이상하게 보일 수 있지만 다음과 같습니다.
var addEventsAndStuff;
(addEventsAndStuff = function(){
// add events, and ... stuff
})();
JavaScript에서 함수를 정의하는 방법에는 두 가지가 있습니다. 함수 선언 :
function foo(){ ... }
이고 함수식, 임의의 상기 이외의 함수를 정의하는 방법 :
var foo = function(){};
(function(){})();
var foo = {bar : function(){}};
...기타
함수 표현식은 이름을 지정할 수 있지만 그 이름은 포함하는 범위로 전파되지 않습니다. 이 코드가 유효 함을 의미합니다.
(function foo(){
foo(); // recursion for some reason
}());
그러나 이것은 아닙니다 :
(function foo(){
...
}());
foo(); // foo does not exist
따라서 함수의 이름을 지정하고 즉시 호출하려면 지역 변수를 정의하고 함수를 표현식으로 할당 한 다음 호출해야합니다.
이것에 대한 좋은 속기가 있습니다 (함수 할당에 변수를 선언 할 필요가 없습니다) :
var func = (function f(a) { console.log(a); return f; })('Blammo')
이 설정에는 아무런 문제가 없습니다 (또는 존재합니까?). 조금 부드럽게 할 수 있습니까?
대신 이벤트 위임을 사용하십시오. 여기서 사라 지지 않는 컨테이너에서 이벤트를 실제로 관찰 한 다음 event.target
(또는 event.srcElement
IE에서) 이벤트가 실제로 발생한 위치를 파악하고 올바르게 처리합니다.
이렇게하면 핸들러를 한 번만 연결하고 콘텐츠를 교체해도 계속 작동합니다.
다음은 도우미 라이브러리를 사용하지 않는 이벤트 위임의 예입니다.
(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 one handler 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.
Modern JavaScript libraries like jQuery, Prototype, YUI, Closure, or any of several others should 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).
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):
(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);
You might want to create a helper function like this:
function defineAndRun(name, func) {
window[name] = func;
func();
}
defineAndRun('addEventsAndStuff', function() {
alert('oele');
});
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;
}()
);
Even simpler with 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"
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();
Try to do like that:
var addEventsAndStuff = (function(){
var func = function(){
alert('ole!');
};
func();
return func;
})();
'Program Tip' 카테고리의 다른 글
네임 스페이스를 "사용하지"하려면 어떻게해야합니까? (0) | 2020.10.14 |
---|---|
C #에서 system.net.webrequest를 사용하여 JSON 응답을 얻는 방법은 무엇입니까? (0) | 2020.10.14 |
정적으로 링크 된 라이브러리 간의 기호 충돌을 처리하는 방법은 무엇입니까? (0) | 2020.10.14 |
char의 기본값은 무엇입니까? (0) | 2020.10.14 |
AngularJS : ng-model이 확인란에 대해 ng-checked에 바인딩되지 않음 (0) | 2020.10.14 |