답변:
"실행되지 않음"이 "두 번 이상 호출 될 때 아무것도하지 않음"을 의미하는 경우 클로저를 만들 수 있습니다.
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
@Vladloffe (현재 삭제됨)의 주석에 대한 답변 : 전역 변수를 사용하면 다른 코드에서 "executed"플래그의 값을 재설정 할 수 있습니다 (선택한 이름에 관계없이). 클로저를 사용하면 다른 코드는 실수로 또는 고의로 그렇게 할 수 없습니다.
여기에서 다른 답변이 지적했듯이 여러 라이브러리 (예 : Underscore 및 Ramda )에는 함수를 인수로 받아들이고 제공된 함수를 정확히 한 번 호출하는 다른 함수를 반환 하는 작은 유틸리티 함수 (일반적으로 once()[*] )가 있습니다. 반환 된 함수가 여러 번 호출됩니다. 반환 된 함수는 제공된 함수에서 처음 반환 된 값도 캐시하고 후속 호출에서 반환합니다.
그러나 이러한 타사 라이브러리를 사용하지 않지만 위에서 제공 한 nonce 솔루션이 아닌 이러한 유틸리티 기능을 여전히 원하면 구현하기가 쉽습니다. 내가 본 가장 좋은 버전은 David Walsh가 게시 한 것입니다 .
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
나는 변화하는 경향이 있습니다 fn = null; 하는fn = context = null; . 클로저가 context한 번에 대한 참조를 유지할 이유가 없습니다 fn.
[*] 하지만, jQuery에 대한 Drupal 확장 과 같은 다른 라이브러리에는 once()매우 다른 작업을 수행 하는 이름 이 지정된 함수가있을 수 있습니다 .
재사용 가능한 NOOP (작동 없음) 기능으로 교체하십시오 .
// this function does nothing
function noop() {};
function foo() {
foo = noop; // swap the functions
// do your thing
}
function bar() {
bar = noop; // swap the functions
// do your thing
}
setInterval(foo, 1000)-그리고 이미 이것은 더 이상 작동하지 않습니다. 현재 범위에서 참조를 덮어 쓰고 있습니다.
function myFunc(){
myFunc = function(){}; // kill it as soon as it was called
console.log('call once and never again!'); // your stuff here
};
<button onClick=myFunc()>Call myFunc()</button>
var myFunc = function func(){
if( myFunc.fired ) return;
myFunc.fired = true;
console.log('called once and never again!'); // your stuff here
};
// even if referenced & "renamed"
((refToMyfunc)=>{
setInterval(refToMyfunc, 1000);
})(myFunc)
setInterval()) 참조가 호출 될 때 원래 기능을 반복한다는 것입니다.
UnderscoreJs에는 underscorejs.org/#once 라는 기능이 있습니다.
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
once논쟁 을 받아들이 는 것이 재미있어 보인다 . 당신은 할 수 squareo = _.once(square); console.log(squareo(1)); console.log(squareo(2));얻을 1에게 모두 통화 squareo. 나는 이것을 이해하고 있는가?
_.once방법을 사용하지 않는 것이 좋습니다 . jsfiddle.net/631tgc5f/1
_. 그런 작은 코드에 대해 전체 라이브러리에 의존하는 것은 권장하지 않습니다.
var quit = false;
function something() {
if(quit) {
return;
}
quit = true;
... other code....
}
단순히 "자체 제거"기능을 사용할 수 있습니다.
function Once(){
console.log("run");
Once = undefined;
}
Once(); // run
Once(); // Uncaught TypeError: undefined is not a function
그러나 오류를 삼키고 싶지 않다면 이것이 최선의 대답이 아닐 수도 있습니다.
다음과 같이 할 수도 있습니다.
function Once(){
console.log("run");
Once = function(){};
}
Once(); // run
Once(); // nothing happens
유형 A의 요소가 없으면 실행할 수 있고 하나 이상의 A 요소가 있으면 함수를 실행할 수없는 스마트 포인터처럼 작동해야합니다.
function Conditional(){
if (!<no elements from type A>) return;
// do stuff
}
Once콜백으로 전달 된 경우 (예 :) 작동하지 않습니다 setInterval(Once, 100). 원래 함수는 계속 호출됩니다.
이 시도
var fun = (function() {
var called = false;
return function() {
if (!called) {
console.log("I called");
called = true;
}
}
})()
다음 invalidate과 함께 작동하는 재사용 가능한 기능 setInterval:
var myFunc = function (){
if (invalidate(arguments)) return;
console.log('called once and never again!'); // your stuff here
};
const invalidate = function(a) {
var fired = a.callee.fired;
a.callee.fired = true;
return fired;
}
setInterval(myFunc, 1000);
JSBin에서 시도해보십시오. https://jsbin.com/vicipar/edit?js,console
다음은 JSFiddle의 예입니다. http://jsfiddle.net/6yL6t/
그리고 코드 :
function hashCode(str) {
var hash = 0, i, chr, len;
if (str.length == 0) return hash;
for (i = 0, len = str.length; i < len; i++) {
chr = str.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
var onceHashes = {};
function once(func) {
var unique = hashCode(func.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]);
if (!onceHashes[unique]) {
onceHashes[unique] = true;
func();
}
}
다음과 같이 할 수 있습니다.
for (var i=0; i<10; i++) {
once(function() {
alert(i);
});
}
그리고 한 번만 실행됩니다. :)
초기 설정 :
var once = function( once_fn ) {
var ret, is_called;
// return new function which is our control function
// to make sure once_fn is only called once:
return function(arg1, arg2, arg3) {
if ( is_called ) return ret;
is_called = true;
// return the result from once_fn and store to so we can return it multiply times:
// you might wanna look at Function.prototype.apply:
ret = once_fn(arg1, arg2, arg3);
return ret;
};
}
Node.js를 사용하거나 browserify로 JavaScript를 작성하는 경우 "once"npm 모듈을 고려하십시오 .
var once = require('once')
function load (file, cb) {
cb = once(cb)
loader.load('file')
loader.once('load', cb)
loader.once('error', cb)
}
나중에 함수를 재사용 할 수 있기를 원한다면 위의 ed Hopp의 코드를 기반으로 잘 작동합니다 (원래 질문에서이 추가 기능을 요구하지 않았 음을 알고 있습니다!)
var something = (function() {
var executed = false;
return function(value) {
// if an argument is not present then
if(arguments.length == 0) {
if (!executed) {
executed = true;
//Do stuff here only once unless reset
console.log("Hello World!");
}
else return;
} else {
// otherwise allow the function to fire again
executed = value;
return;
}
}
})();
something();//Hello World!
something();
something();
console.log("Reset"); //Reset
something(false);
something();//Hello World!
something();
something();
출력은 다음과 같습니다.
Hello World!
Reset
Hello World!
밑줄 "한 번"기능 사용 시도 :
var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.
Ramda를 사용하는 경우 "once" 함수를 사용할 수 있습니다 .
문서에서 인용 :
기능 (a… → b) → (a… → b) v0.1.0에 추가 된 매개 변수
함수 fn을 받아들이고 반환 된 함수가 호출되는 횟수에 관계없이 fn이 한 번만 호출 될 수 있도록 fn 호출을 보호하는 함수를 반환합니다. 계산 된 첫 번째 값은 후속 호출에서 반환됩니다.
var addOneOnce = R.once(x => x + 1);
addOneOnce(10); //=> 11
addOneOnce(addOneOnce(50)); //=> 11
가능한 한 간단하게
function sree(){
console.log('hey');
window.sree = _=>{};
}
결과를 볼 수 있습니다

this대신 사용하십시오window
JQuery는 one () 메서드를 사용하여 함수를 한 번만 호출 할 수 있습니다 .
let func = function() {
console.log('Calling just once!');
}
let elem = $('#example');
elem.one('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery one()</button>
</div>
JQuery 메서드 on ()을 사용한 구현 :
let func = function(e) {
console.log('Calling just once!');
$(e.target).off(e.type, func)
}
let elem = $('#example');
elem.on('click', func);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Function that can be called only once</p>
<button id="example" >JQuery on()</button>
</div>
네이티브 JS를 사용한 구현 :
let func = function(e) {
console.log('Calling just once!');
e.target.removeEventListener(e.type, func);
}
let elem = document.getElementById('example');
elem.addEventListener('click', func);
<div>
<p>Functions that can be called only once</p>
<button id="example" >ECMAScript addEventListener</button>
</div>
if (!window.doesThisOnce){
function myFunction() {
// do something
window.doesThisOnce = true;
};
};
이것은 무한 루프를 방지하는 데 유용합니다 (jQuery 사용).
<script>
var doIt = true;
if(doIt){
// do stuff
$('body').html(String($('body').html()).replace("var doIt = true;",
"var doIt = false;"));
}
</script>
네임 스페이스 오염이 걱정된다면 "doIt"을 임의의 긴 문자열로 대체하십시오.