操作がない場合のJavaScriptの規則は何ですか?


121

操作がない場合のJavaScriptの規則は何ですか?Python passコマンドのように。

  • 1つのオプションは、単に空の関数です。 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で「ノーオペレーション」関数を指定するための最良の方法は何ですか?

EDIT2:これらの1つはどうですか?

true;
false;
0;
1;
null;

7
なぜ単純なifステートメントではないのですか?
epascarello、2014

11
これらの代替手段0はどれも、効果的にはこれ以上良くありません(または悪い)。私が正しいことはif (a === 1) doSomething();? :それが意味をなさないときに使用しないことです。
2014

6
あなたは副作用で三項演算子を乱用しています。必要にif (statement) action; else ;
応じて

はいfalseまたは0機能します。nullノーオペレーションを表現する良い方法です。
マット

3
なんらかの理由で3進数に必要なものが表示されないことを願っています...コードを複雑にしてクールに感じているように見えます(すべて完了しました!)
Stachu

回答:


95

元の質問に答えるために、純粋なJavascriptでの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を実行するために何もしないように見えるため(つまり、CPUサイクルを節約するため)、これは「真のnoop」ですが、これに関連するいくつかのパフォーマンスの問題がある可能性があります(コメントまたは他の人にも言及されています)他の答え)。

ただし、そうは言っても、独自の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では角度2+(んが、ネイティブ実装を持っているように見えるではない-上記のように独自のものを使用)、エンバー jQueryの Lodash NodeJS RAMDAリアクト(んが、ネイティブ実装を持っているように見えるではない-あなた自身を使用上記のように)、 RxJSアンダースコア

BOTTOM LINE:Function.prototypeはJavascriptでNOOPを表現するエレガントな方法ですが、しかし、その使用に関連するいくつかのパフォーマンスの問題があるかもしれません。したがって、独自のものを定義して使用するか(上記を参照)、コードで使用している可能性のあるライブラリ/フレームワークによって定義されたものを使用できます。


5
これが答えです。Function.prototype()タイムアウトを必要とせず、すぐに実行したい場合でも使用できます。
15

1
setTimeout(Function(), 10000);
iegik 2016年

@iegik:+1。はい。それで合っています。以下はすべて同等です:setTimeout(function(){}、10000); またはsetTimeout(new Function()、10000); OR setTimeout(Function()、10000); またはsetTimeout(Function、10000); JavaScript文法とFunctionコンストラクターの実装がこれらの構成体を許可するためです。
アランCS

5
ES6で、またはbabelまたは別のトランスパイラーを(( )=>{};)技術的に使用して、純粋なJS を使用しfunction () {}ます。
Ray Foss

2
プログラムでデバッグコードを効率的にオフにするための何もしないような構造を見つけることに興味がありました。C / C ++では、マクロを使用していました。私はfnをFunction.prototypeに割り当てて時間を測定し、結果を比較して、関数内にifステートメントがあり、すぐに戻るようにしました。また、ループから関数を完全に削除した結果と比較しました。残念ながら、Function.prototypeはまったく機能しませんでした。空の関数を呼び出すと、パフォーマンスがはるかに優れており、単純な「if」テストを使用して関数を呼び出すよりも高速に戻ります。
ベアバリン16

72

最も簡潔で高性能なnoopは、空の矢印関数です()=>{}

Arrow関数は、IEを除くすべてのブラウザーでネイティブに機能します(必要な場合は、Babel変換があります)。 MDN


()=>{}Function.Prototype

  • ()=>{}87%高速化よりもFunction.prototypeクローム67インチ
  • ()=>{}25%高速化よりもFunction.prototypeFirefoxの60インチ
  • ()=>{}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大幅に低速ですが、他のオプションのどれも明確な利点はありません。
Lucas Werkmeister 2017年

_=>{}1文字少なく、同じことを行います。
Ross Attrill

@RossAttrill *同様のもの- _=>{}単一のパラメーターがあります。誰かが適度に厳密な設定でTypeScriptを使用している場合、それはコンパイルされません。これを呼び出すと、IDEは、任意のタイプ(JavaScriptと特にvscodeのTypeScriptの両方)にすることができる単一のパラメーターを受け入れると通知する可能性があります。
チェンバレン

15

ここで達成しようとしていることは何でも間違っています。三項式、完全なステートメントとしてではなく、式でのみ使用するものとします。そのため、質問に対する答えは次のとおりです。

あなたの提案のどれも、代わりに行います:

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

その後、コードは理解しやすく、読みやすく、可能な限り効率的です。

なぜそれが簡単なのに、それをより難しくするのですか

編集:

では、「操作なし」コマンドは基本的に下位のコード構造を示しているのでしょうか。

あなたは私のポイントを逃しています。上記はすべて3値式に関するものx ? y : zです。

しかし、no operationコマンドは、Javascriptなどの高水準言語では意味がありません。

通常、これは、アセンブリーやCなどの低レベル言語で、プロセッサーがタイミングを目的として1つの命令に対して何も行わないようにする方法として使用されます。

JSでは、あなたがいるかどうか0;null;function () {};または空のステートメント、それはそれを読んでいるとき、それは通訳によって無視されるという大きなチャンスがありますが、前にそれは解釈されますので、最後に、あなたは自分のプログラムがあることにしますよほんのわずかな時間でゆっくりとロードされます。Nota Bene:私はこれを想定しています。私が広く使用されているJSインタープリターには関与しておらず、各インタープリターが独自の戦略を持っている可能性があるからです。

$.noop()またはのようなもう少し複雑なものを使用する場合var foo = function () {}; foo()、インタプリタは、関数スタックの数バイトと数サイクルを損なうことになる、役に立たない関数呼び出しを行う可能性があります。

$.noop()存在するような関数が見られる唯一の理由は、コールバックを呼び出せない場合に例外をスローするイベント関数にコールバック関数を引き続き提供できるようにすることです。しかし、それは必然的にあなたが与える必要のある関数であり、それにnoop名前を付けるのは良い考えですので、意図的に空の関数を与えることを読者(そして6か月後にはあなたかもしれません)に伝えます。

結局、「劣った」または「優れた」コード構造などはありません。あなたの道具の使い方は正しいか間違っています。例として三進法を使用することは、ねじ込みたいときにハンマーを使用するようなものです。機能しますが、そのネジに何かを掛けることができるかどうかはわかりません。

「劣っている」または「優れている」と見なすことができるのは、コードに組み込んだアルゴリズムとアイデアです。しかし、それは別のことです。


1
では、「操作なし」コマンドは基本的に下位のコード構造を示しているのでしょうか。
kmiklas 14

3
@kmiklas:アセンブラの外では、NOOPの正当な必要性を見つけたとは言えません。
Matt Burland、2014

@zmo:あなたのコメントが三進表現にどのように関連しているかについてのあなたのポイントは理解しています。これは、「操作なし」関数の呼び出しの単なる例にすぎないという私の見落としがあったようです。
kmiklas 14

1
もちろん、何もしない機能を必要とする/必要とする理由があります。何かについての12秒間の深い考えに基づいて広範な一般化を行わないでください。JavaScriptは、関数を変数として完全に制御可能にする言語です。明示的なテストなしで関数を無効にする必要があるとしましょうか?これはそのために最適です。デバッグステートメントなど、頻繁に表示される関数がある場合、関数が表示されるたびに変数をテストするために追加のコードを追加する必要がなく、関数をno-opに再割り当てすることでオフにできると便利です。 。
ベアバリン

2
@bearvarine私のことを高く評価してくれてありがとう:-D。あなたのコメントは完全に正しいですが、実際にはコード設計ではなく、ハックを使用したモックアップ設計です。あなたが説明することはサルのパッチングとも呼ばれ、それには理由があります;-)
zmo

7

jQuery noop()は、要求された関数が使用できないときにデフォルトの関数を提供することにより、コードのクラッシュを防ぐことを主な目的としています。たとえば、次のコードサンプルを考えると、が定義されていない$.noop場合に選択fakeFunctionされ、次の呼び出しがfnクラッシュするのを防ぎます。

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

次に、noop()コード内のどこにでも同じ空の関数を何度も書き込むことを避けることで、メモリを節約できます。ちなみに、(トークンあたり6バイト節約)$.noopより少し短いですfunction(){}。したがって、コードと空の関数パターンとの間に関係はありません。を使用するかnullfalse必要に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
ただし、関数を提供する必要がある場合もあります。たとえばpromise(then(fn、fn))では、最初の関数ではなく2番目の関数を提供したい場合があります。したがって、プレースホルダーに何かが必要です...mypromise.then($.noop, myErrorhandler);
John Henckel '19

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
コードウィスパー2017

4
単に0を割り当てています。IMO noopは、undefined結果を評価する関数である必要があります。
チェンバレン2017

1
このステートメントはどうですか(0); 0?を割り当てると、varと等号はどこにありますか?(0)の前に関数名がないので、これがどのように引数になるのかわかりませんか?typeof((0))を試すと、数値として返されます。私が質問に答えるとき、私はNOPを模倣するために使用するステートメントを提供していましたが、私は単に使用するために私の答えを変更したいと思っています。空のステートメントを表す
Eggs

1
私は(0); OPの質問に対する許容可能な解決策です。何もしないステートメントではなく、何もしない関数を探しているときにこのページを見つけたので、人々は混乱していると思います。OPは、最初にfunction(){}解決策として提案しても役に立ちません。通話(0)()が発生しますTypeError: 0 is not a function
ベンジャミン

と言っていましたvar a = (0);。no-opはメモリを変更するべきではなく、割り当ての例はそれを行います。(0)役に立たないノーオペレーション(ここではあなたの例では、特別なものは何もありませんので、これらの無限の数がJavaScriptである)自分自身で考えることができます。
チェンバレン

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.