web-dev-qa-db-ja.com

オプションのコールバック用のJavaScriptスタイル

私は時々コールバックを受け取り、それを実行するいくつかの関数を持っています。コールバックが定義/機能されているかどうかを確認するのは良いスタイルですか、それとももっと良い方法がありますか?

例:

function save (callback){
   .....do stuff......
   if(typeof callback !== 'undefined'){
     callback();
   };
};
86
henry.oswald

私は個人的に好む

typeof callback === 'function' && callback();

typeofコマンドは危険ですが、"undefined"および"function"にのみ使用する必要があります

typeof !== undefinedの問題は、ユーザーが定義された値を渡す可能性があることです関数ではない

131
Raynos

次のこともできます。

var noop = function(){}; // do nothing.

function save (callback){
   callback = callback || noop;
   .....do stuff......
};

callbackをいくつかの場所で使用する場合に特に役立ちます。

さらに、jQueryを使用している場合、すでにそのような関数があります。これは $。noop と呼ばれます

45
Pablo Fernandez

単純に

if (callback) callback();

タイプが何であれ、コールバックが提供されている場合はコールバックを呼び出すことを好みます。黙って失敗させないようにしてください。実装者は間違った引数を渡したことを認識し、修正できます。

33
ninja123

ECMAScript 6

// @param callback Default value is a noop fn.
function save(callback = ()=>{}) {
   // do stuff...
   callback();
}
8
Lucio

コールバックをオプションにするのではなく、デフォルトを割り当てて、それが何であれそれを呼び出すだけです

const identity = x =>
  x

const save (..., callback = identity) {
  // ...
  return callback (...)
}

使用するとき

save (...)              // callback has no effect
save (..., console.log) // console.log is used as callback

このようなスタイルは continuation-passing style と呼ばれます。配列入力の可能なすべての組み合わせを生成する実際の例combinationsは次のとおりです。

const identity = x =>
  x

const None =
  Symbol ()

const combinations = ([ x = None, ...rest ], callback = identity) =>
  x === None
    ? callback ([[]])
    : combinations
        ( rest
        , combs =>
            callback (combs .concat (combs .map (c => [ x, ...c ])))
        )

console.log (combinations (['A', 'B', 'C']))
// [ []
// , [ 'C' ]
// , [ 'B' ]
// , [ 'B', 'C' ]
// , [ 'A' ]
// , [ 'A', 'C' ]
// , [ 'A', 'B' ]
// , [ 'A', 'B', 'C' ]
// ]

combinationsは継続渡しスタイルで定義されているため、上記の呼び出しは事実上同じです

combinations (['A', 'B', 'C'], console.log)
// [ []
// , [ 'C' ]
// , [ 'B' ]
// , [ 'B', 'C' ]
// , [ 'A' ]
// , [ 'A', 'C' ]
// , [ 'A', 'B' ]
// , [ 'A', 'B', 'C' ]
// ]

また、結果に対して何か他のことをするカスタム継続を渡すこともできます

console.log (combinations (['A', 'B', 'C'], combs => combs.length))
// 8
// (8 total combinations)

継続渡しスタイルを使用して驚くほどエレガントな結果を得ることができます

const first = (x, y) =>
  x

const fibonacci = (n, callback = first) =>
  n === 0
    ? callback (0, 1)
    : fibonacci
        ( n - 1
        , (a, b) => callback (b, a + b)
        )
        
console.log (fibonacci (10)) // 55
// 55 is the 10th fibonacci number
// (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...)
1
user633183

同じスニペットを何度も何度も見るのにうんざりしました。

  var cb = function(g) {
    if (g) {
      var args = Array.prototype.slice.call(arguments); 
      args.shift(); 
      g.apply(null, args); 
    }
  };

私は次のようなことをする関数を何百も持っています

  cb(callback, { error : null }, [0, 3, 5], true);

または何でも...

私は「それが機能していることを確認する」戦略全体に懐疑的です。唯一の正当な値は、関数または偽です。誰かがゼロ以外の数字または空でない文字列を渡すと、どうしますか?問題を無視することでどのように解決しますか?

1
Malvolio

有効な関数は、Functionプロトタイプに基づいています。以下を使用します。

if (callback instanceof Function)

コールバックが関数であることを確認する

1
G. Moore

コールバックを実行するための基準が、定義されているかどうかにかかわらず、大丈夫です。また、実際に機能するかどうかも確認することをお勧めします。

0
Mrchief

ArgueJS で簡単に行えます:

function save (){
  arguments = __({callback: [Function]})
.....do stuff......
  if(arguments.callback){
    callback();
  };
};
0
zVictor

私はコーヒースクリプトに移行して以来、デフォルトの引数がこの問題を解決する良い方法であることがわかりました

doSomething = (arg1, arg2, callback = ()->)->
    callback()
0
henry.oswald