작동하지 않는 JavaScript 규칙은 무엇입니까?


121

작업 없음에 대한 JavaScript 규칙은 무엇입니까? Python pass명령과 같습니다.

  • 한 가지 옵션은 단순히 빈 함수입니다. function() {}
  • jQuery는 $.noop()단순히 위의 빈 함수를 호출하는을 제공합니다 .
  • 단순히 false또는 값을 입력해도 0됩니까?

맥락에서 ...이 모든 것이 Chrome에서 오류를 발생시키지 않고 작동합니다.

var a = 2;
(a === 1) ? alert(1) : function() {};
(a === 1) ? alert(1) : $.noop();
(a === 1) ? alert(1) : false;
(a === 1) ? alert(1) : 0;

편집 : 많은 사람들이 "이러지 마세요! 코드 구조를 변경하세요!"라고 대답했습니다. 이것은 누군가가 브라우저를 스니핑하는 방법을 묻는 게시물을 생각 나게합니다. 그는 "그렇게하지 마세요! 그것은 악합니다"라는 글을 많이 받았지만 아무도 그에게 브라우저 냄새를 맡는 방법을 알려주지 않았습니다 . 이것은 코드 리뷰가 아닙니다. 변경할 수없는 레거시 코드를 처리하고 있으며 일부 함수가 전달되지 않으면 오류가 발생한다고 상상해보십시오. 또는 간단히 말해서 고객이 원하는 방식이고 고객 이 비용을 지불합니다 . 따라서 정중하게 질문에 답하십시오 . JavaScript에서 "no operation"기능을 지정하는 가장 좋은 방법은 무엇입니까?

EDIT2 : 이들 중 하나는 어떻습니까?

true;
false;
0;
1;
null;

7
간단한 if 문이 아닌 이유는 무엇입니까?
epascarello 2014

11
에 대한 대안 0중 어느 것도 효과적으로 더 좋거나 나쁘지 않습니다. 해야 할 옳은 일은 말이되지 않을 때는 if (a === 1) doSomething();사용 ? :하지 않는 것입니다.
Pointy

6
부작용으로 삼항 연산자를 남용하고 있습니다. 꼭해야한다면if (statement) action; else ;
mplungjan 2014

false또는 0작동합니다. nullno-op을 표현하는 좋은 방법입니다.
Matt

3
삼항이 어떤 이유에서인지 우리가 볼 수없는 필요성이 있기를 바랍니다 ... 아주 멋지게 느껴지도록 코드를 복잡하게
만드는

답변:


95

원래의 질문에 답하기 위해, 순수 자바 스크립트에서 noop 함수의 가장 우아하고 깔끔한 구현은 ( 여기 에서도 논의 된 바와 같이 ) Function.prototype 입니다. 이 때문입니다:

  1. Function.prototype은 함수입니다.

typeof Function.prototype === "function" // returns true

  1. 함수로 호출 할 수 있으며 기본적으로 여기에 표시된대로 아무것도 수행하지 않습니다.
setTimeout(function() {
      console.log('Start: ', Date.now());
      Function.prototype();
      console.log('End  : ', Date.now());
    }, 1000);

대부분의 브라우저가 이러한 방식으로 정의 된 noop를 실행하기 위해 아무것도하지 않는 것 같기 때문에 이것이 "진정한 noop"이지만 (따라서 CPU주기를 절약합니다) 이와 관련된 성능 문제가있을 수 있습니다 (다른 사람이 의견이나 다른 답변).

그러나 자신의 noop 함수를 쉽게 정의 할 수 있으며 실제로 많은 라이브러리와 프레임 워크도 noop 함수를 제공합니다. 다음은 몇 가지 예입니다.

var noop = function () {};           // Define your own noop in ES3 or ES5
const noop = () => {};               // Define in ES6 as Lambda (arrow function)
setTimeout(noop, 10000);             // Using the predefined noop

setTimeout(function () {} , 10000);  // Using directly in ES3 or ES5
setTimeout(() => {} , 10000);        // Using directly in ES6 as Lambda (arrow function)

setTimeout(angular.noop, 10000);     // Using with AngularJS 1.x
setTimeout(jQuery.noop, 10000);      // Using with jQuery

다음은 noop 함수 (또는 관련 토론 또는 Google 검색)의 다양한 구현의 알파벳순 목록입니다.

AngularJS 1.x , Angular 2+ (기본 구현이없는 것 같음-위에 표시된대로 직접 사용), Ember , jQuery , Lodash , NodeJS , Ramda , React (기본 구현이없는 것 같음 -직접 사용 위와 같이), RxJS , 밑줄

BOTTOM LINE : Function.prototype은 Javascript에서 noop를 표현하는 우아한 방법이지만 사용과 관련된 성능 문제가있을 수 있습니다. 따라서 위에 표시된대로 직접 정의하고 사용하거나 코드에서 사용할 수있는 라이브러리 / 프레임 워크에 의해 정의 된 것을 사용할 수 있습니다.


5
이것이 답이되어야합니다. Function.prototype()시간 제한이 필요하지 않고 즉시 실행되기를 원하는 경우 에도 사용할 수 있습니다.
springloaded dec

1
setTimeout(Function(), 10000);
이직

@iegik : +1. 그래 정확 해. 다음은 모두 동일합니다. setTimeout (function () {}, 10000); 또는 setTimeout (new Function (), 10000); 또는 setTimeout (Function (), 10000); 또는 setTimeout (Function, 10000); Javascript 문법과 Function 생성자 구현이 이러한 구성을 허용하기 때문입니다.
Alan CS

5
ES6에서 또는 바벨 또는 다른 트랜스 파일러 사용 (( )=>{};) 기술적으로 Pure JS로 사용하고 훨씬 짧지 function () {}만 정확히 동등합니다.
Ray Foss

2
내 프로그램에서 디버그 코드를 효율적으로 해제 할 수있는 no-op-like 구조를 찾는 데 관심이있었습니다. C / C ++에서는 매크로를 사용했을 것입니다. 내 fn을 Function.prototype에 할당하고 시간을 측정하여 결과를 단순히 함수 내에 if 문이있는 것과 비교하여 즉시 반환합니다. 또한 루프에서 함수를 완전히 제거한 결과와도 비교했습니다. 불행히도 Function.prototype은 전혀 잘 수행되지 않았습니다. 빈 함수를 호출하는 것은 내부에 간단한 'if'테스트가있는 함수를 호출하여 반환하는 것보다 훨씬 더 빠른 성능을 제공합니다.
bearvarine

72

가장 간결하고 성능이 좋은 무 조작은입니다 빈 화살표 기능 : ()=>{}.

화살표 함수 는 IE를 제외한 모든 브라우저에서 기본적으로 작동합니다 ( 필요한 경우 바벨 변환 이 있음). MDN


()=>{}Function.Prototype

  • ()=>{}이다 87 % 더 빠른 것보다 Function.prototype크롬 육십칠인치
  • ()=>{}이다 25 % 더 빠른 것보다 Function.prototype파이어 폭스 육십인치
  • ()=>{} 이다 85 % 더 빠른 것보다 Function.prototype가장자리에서 (2018년 6월 15일) .
  • ()=>{} 이다 65 % 미만의 코드 보다 Function.prototype.

아래 테스트는 화살표 함수를 사용하여에 바이어스를 부여 Function.prototype하지만 화살표 함수가 확실한 승자입니다.

const noop = ()=>{};
const noopProto = Function.prototype;

function test (_noop, iterations) {
    const before = performance.now();
    for(let i = 0; i < iterations; i++) _noop();
    const after = performance.now();
    const elapsed = after - before;
    console.info(`${elapsed.toFixed(4)}MS\t${_noop.toString().replace('\n', '')}\tISNOOP? ${_noop() === undefined}`);
    return elapsed;
}

const iterations = 10000000
console.info(`noop time for ${iterations.toLocaleString()} iterations`)
const timings = {
    noop: test(noop, iterations),
    noopProto: test(noopProto, iterations)
}

const percentFaster = ((timings.noopProto - timings.noop)/timings.noopProto).toLocaleString("en-us", { style: "percent" });
console.info(`()=>{} is ${percentFaster} faster than Function.prototype in the current browser!`)


1
몇 가지 옵션을 비교하기 위해 jsPerf 테스트를 만들었습니다 : noop-function . Firefox 54에서는 모든 대안이 거의 동등한 것 같습니다. Chromium 58에서는 Function.prototype상당히 느리지 만 다른 옵션에는 확실한 이점이 없습니다.
루카스 Werkmeister

_=>{}한 문자가 적고 같은 일을합니다.
Ross Attrill

@RossAttrill * 유사한 것- _=>{}단일 매개 변수가 있습니다. 누군가 합리적으로 엄격한 구성으로 TypeScript를 사용하는 경우 컴파일되지 않습니다. 이를 호출하면 IDE는 모든 유형 (JavaScript 및 특히 vscode의 TypeScript 모두) 일 수있는 단일 매개 변수를 허용한다고 알려줄 것입니다.
cchamberlain

15

여기서 성취하려는 경향은 잘못된 것입니다. 삼항 표현은 하지 않는다 질문에 대한 대답은, 그래서 오직 식, 전체 문장로 사용할 수 :

귀하의 제안 사항이 아니라 대신 다음을 수행하십시오.

var a = 2;
if (a === 1)
    alert(1)
// else do nothing!

그러면 코드는 쉽게 이해하고 읽을 수 있으며 얻을 수있는 한 효율적입니다.

간단 할 수 있는데 왜 더 어렵게 만들까요?

편집하다:

그렇다면 "no-operation"명령이 기본적으로 열등한 코드 구조를 나타내는 것일까 요?

당신은 내 요점을 놓치고 있습니다. 위의 모든 것은 삼항식에 관한 것 x ? y : z입니다.

그러나 no operation 명령은 Javascript와 같은 고급 언어에서는 의미가 없습니다.

일반적으로 어셈블리 또는 C와 같은 하위 수준 언어에서 프로세서가 타이밍 목적을 위해 하나의 명령에 대해 아무것도하지 않도록하는 방법으로 사용됩니다.

JS에서, 당신이 있는지 0;, null;, function () {};또는 하늘의 문, 그것을 읽을 때 그것이 통역원에 의해 무시됩니다 큰 기회가있다, 그러나 전에 그것을 해석됩니다, 그래서 결국, 당신은 당신의 프로그램이 될 수 있도록거야 아주 작은 시간만큼 느리게로드됩니다. Nota Bene : 나는 널리 사용되는 JS 인터프리터에 관여하지 않았기 때문에 이것을 가정하고 있으며 각 인터프리터가 자체 전략을 가질 가능성이 있습니다.

경우 당신은 복잡 좀 더 뭔가를 사용하여 같은 $.noop()하거나 var foo = function () {}; foo(), 다음 인터프리터가 함수 스택의 몇 바이트를 망치고 결국 것이다 unuseful 함수 호출, 몇 사이클을 수행 할 수 있습니다.

내가 $.noop()존재 하는 것과 같은 함수를 보는 유일한 이유 는 콜백을 호출 할 수없는 경우 예외를 발생시키는 일부 이벤트 함수에 콜백 함수를 계속 제공 할 수 있기 때문입니다. 그러나 그것은 반드시 당신이 제공해야 할 기능이고, noop이름을 부여하는 것은 좋은 생각이므로 독자들 (그리고 그것은 6 개월 후에 당신이 될 수 있음)에게 의도적으로 빈 기능을 제공한다고 말하는 것입니다.

결국, "열등한"또는 "우수한"코드 구조와 같은 것은 없습니다. 당신은 당신의 도구를 사용하는 방법에있어서 옳거나 그르다. 당신의 예로 삼항을 사용하는 것은 나사를 조이고 싶을 때 망치를 사용하는 것과 같다. 작동하지만 나사에 무언가를 걸 수 있는지 확실하지 않습니다.

"열등"또는 "우수"로 간주 될 수있는 것은 코드에 넣은 알고리즘과 아이디어입니다. 그러나 그것은 또 다른 것입니다.


1
그렇다면 "no-operation"명령은 기본적으로 열등한 코드 구조를 나타내는 것일까 요?
kmiklas 2014

3
@kmiklas : 어셈블러 외부에서 NOOP에 대한 합법적 인 요구를 발견했다고 말할 수 없습니다.
Matt Burland 2014

@zmo : 귀하의 의견이 삼항 표현과 어떻게 관련되는지에 대한 귀하의 요점을 이해합니다. 모든 사람들이 이것이 "No Operation"기능에 대한 호출의 예시 일 뿐이라는 내 요점을 놓친 것 같습니다.
kmiklas 2014

1
물론 작동하지 않는 기능을 원하거나 필요로하는 이유가 있습니다. 무언가에 대한 12 초의 깊은 생각을 기반으로 광범위한 일반화를하지 마십시오. JavaScript는 함수를 변수로 완전히 제어 할 수있는 언어입니다. 명시적인 테스트없이 기능을 비활성화해야한다고 가정 해 보겠습니다. 이것은 완벽 할 것입니다. 디버그 문과 같이 자주 나타나는 함수가있는 경우 함수가 나타날 때마다 일부 변수를 테스트하기 위해 추가 코드를 추가하는 것보다 함수를 no-op으로 다시 할당하여 기능을 끌 수있는 것이 좋습니다. .
bearvarine

2
@bearvarine 당신이 나에 대해 가지고있는 높은 의견에 감사드립니다 :-D. 당신은 당신의 의견에 절대적으로 맞지만 실제로 코드 디자인이 아니라 해킹을 사용한 모형 디자인입니다. 당신이 설명하는 것은 원숭이 패치라고도 불리며, 그 이유가 있습니다 ;-)
zmo

7

jQuery noop()는 대부분 요청 된 기능을 사용할 수 없을 때 기본 기능을 제공하여 코드 충돌을 방지하기위한 것이라고 생각 합니다. 예를 들어 다음 코드 샘플을 고려 $.noop하면 fakeFunction이 정의되지 않은 경우 선택되어에 대한 다음 호출이 fn충돌 하지 않도록합니다 .

var fn = fakeFunction || $.noop;
fn() // no crash

그런 다음 noop()코드의 모든 곳에서 동일한 빈 함수를 여러 번 작성하지 않도록하여 메모리를 절약 할 수 있습니다. 그건 그렇고, (토큰 당 6 바이트 저장) $.noop보다 약간 짧습니다 function(){}. 따라서 코드와 빈 함수 패턴 사이에는 관계가 없습니다. 사용 null, false또는 0당신이 좋아하는 경우, 귀하의 경우에는 부작용이있을 수 없습니다. 또한이 코드는 ...

true/false ? alert('boo') : function(){};

... 함수를 절대 호출하지 않기 때문에 완전히 쓸모가 없습니다.

true/false ? alert('boo') : $.noop();

... 빈 함수를 호출하기 때문에 훨씬 더 쓸모가 없습니다.

true/false ? alert('boo') : undefined;

삼항 표현식을 if문으로 대체하여 얼마나 쓸모 없는지 확인 합시다 .

if (true/false) {
    alert('boo');
} else {
    $.noop(); // returns undefined which goes nowhere
}

간단히 다음과 같이 작성할 수 있습니다.

if (true/false) alert('boo');

또는 더 짧게 :

true/false && alert('boo');

마지막으로 귀하의 질문에 답하기 위해 "전통적인 무 연산"이 결코 작성되지 않은 것 같습니다.


1
그러나 때로는 기능을 제공해야합니다. 예를 들어 then (fn, fn) 약속을 사용하면 두 번째 기능을 제공하고 싶지만 첫 번째 기능은 제공하지 않을 수 있습니다. 그러므로 당신은 ... 장소 홀더에 대한 뭔가가 필요mypromise.then($.noop, myErrorhandler);
존 헨켈

3

나는 사용한다:

 (0); // nop

이 실행의 실행 시간을 테스트하려면 다음과 같이하십시오.

console.time("mark");
(0); // nop
console.timeEnd("mark");

결과 : 표시 : 0.000ms

사용 Boolean( 10 > 9)은 간단하게 줄일 수 있습니다( 10 > 9) 어떤 반환true . 아이디어를 오는 내가 완전히 예상 하나의 피연산자 사용하는 (0);반환을 false하지만, 단순히 콘솔에서이 테스트를 수행하여 검토 할 수와 같은 인수 등을 반환합니다.

> var a = (0);
< undefined
> a
< 0

1
이 얻을 것이다 시도하는 많은 사람들argument 0 is not a function
코드 속살

4
단순히 0을 할당하는 것입니다. IMO noopundefined결과로 평가하는 함수 여야합니다 .
cchamberlain

1
이 문장은 어떻습니까 (0); 0을 할당합니까?, var와 등호는 어디에 있습니까? (0) 앞에 함수 이름이 없으므로 이것이 어떻게 인수가 될 수 있는지 모르겠습니까? typeof ((0))을 시도하면 숫자로 돌아옵니다. 질문에 대답 할 때 NOP를 모방하는 데 사용하는 진술을 제공했지만 단순히 사용하도록 대답을 변경할 의향이 있습니다. 빈 진술을 나타 내기 위해
Eggs

1
(0); OP의 질문에 대한 수용 가능한 솔루션입니다. 나는 사람들이 아무것도하지 않는 진술이 아니라 아무것도하지 않는 기능을 찾는 동안이 페이지를 발견했기 때문에 혼란스러워하고 있다고 생각 function(){}합니다. 전화 (0)()하면TypeError: 0 is not a function
Benjamin

나는 var a = (0);. no-op은 메모리를 변경해서는 안되며 할당 예제는 그렇게합니다. 그만큼(0)그 자체로는 쓸모없는 연산 고려 될 수있다 (자바 스크립트에서 이러한 무한한 수있다 특별 여기 예를하게 아무것도 없다).
cchamberlain 19

2

Function.prototypeover 를 사용하면 전혀 문제 나 성능 저하가 없습니다 () => {}.

의 주요 이점은 Function.prototype매번 새로운 익명 함수를 다시 정의하는 대신 단일 함수를 사용하는 것입니다. Function.prototype변경되지 않는 일관된 개체 포인터를 제공하므로 기본값을 정의하고 메모 할 때 와 같은 no-op을 사용하는 것이 특히 중요합니다 .

내가 Function.prototype대신 추천 하는 이유 Function는 동일하지 않기 때문입니다.

Function() === Function()
// false

Function.prototype() === Function.prototype()
// true

또한 다른 답변의 벤치 마크는 오해의 소지가 있습니다. 실제로 벤치 마크를 작성하고 실행하는 방법에 따라 Function.prototype성능이 더 빠릅니다 () => {}.

JS 벤치 마크를 신뢰할 수 없습니다. << 특히이 질문에 대한 벤치 마크를 호출합니다.

벤치 마크에서 코드 스타일을 지정하지 마십시오. 유지 관리가 가능한 모든 작업을 수행하고 인터프리터가 장기적으로 최적화하는 방법을 알아 내도록합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.