У меня есть некоторые функции, которые иногда (не всегда) получают обратный вызов и запускают его. Является ли проверка, определен ли обратный вызов / функция, хорошим стилем или есть лучший способ?
Пример:
function save (callback){
.....do stuff......
if(typeof callback !== 'undefined'){
callback();
};
};
javascript
coding-style
callback
Генри Освальд
источник
источник
typeof callback !== undefined
так что'
save()
? Разве это не выдаст ошибку или предупреждение о линтинге из-за отсутствия аргумента? Или это нормально, а обратный звонок - это простоundefined
?Ответы:
Я лично предпочитаю
typeof callback === 'function' && callback();
Однако эта
typeof
команда хитрая и должна использоваться только для"undefined"
и"function"
Проблема
typeof !== undefined
заключается в том, что пользователь может передать определенное значение, а не функциюисточник
typeof
не хитрый. Иногда это расплывчато, но я бы не назвал это изворотливым. Однако мы договорились, что если вы собираетесь вызывать обратный вызов как функцию, лучше всего проверить, что это действительно функция, а не число. :-)"object"
95% случаев.typeof
не вызывает бокса.typeof "foo"
есть"string"
, нет"object"
. На самом деле это единственный реальный способ узнать, имеете ли вы дело со строковым примитивом илиString
объектом. (Возможно, вы думаете об этомObject.prototype.toString
, что очень удобно , но действительно вызывает бокс.)&&
Кстати, замечательно идиоматическое употребление ..toString
это прекрасно для поиска[[Class]]
.Вы также можете:
var noop = function(){}; // do nothing. function save (callback){ callback = callback || noop; .....do stuff...... };
Это особенно полезно, если вы используете
callback
в нескольких местах.Кроме того, если вы используете
jQuery
, у вас уже есть такая функция, она называется $ .noopисточник
callback = callback || function(){};
function save (callback=noop) { ...
Просто делай
if (callback) callback();
Я предпочитаю вызывать обратный вызов, если он указан, независимо от его типа. Не позволяйте ему молча выйти из строя, чтобы разработчик знал, что он передал неверный аргумент, и мог исправить его.
источник
ECMAScript 6
// @param callback Default value is a noop fn. function save(callback = ()=>{}) { // do stuff... callback(); }
источник
Вместо того, чтобы делать обратный вызов необязательным, просто назначьте значение по умолчанию и вызывайте его независимо от того, что
const identity = x => x const save (..., callback = identity) { // ... return callback (...) }
При использовании
save (...) // callback has no effect save (..., console.log) // console.log is used as callback
Такой стиль называется продолжением передачи . Вот реальный пример,
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, ...)
источник
Я так устал видеть один и тот же фрагмент снова и снова, что написал следующее:
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);
или как там ...
Я скептически отношусь ко всей стратегии «убедитесь, что она работает». Единственные допустимые ценности - это функция или ложь. Если кто-то передаст ненулевое число или непустую строку, что вы собираетесь делать? Как ее решить игнорирование проблемы?
источник
save( { callback : confirmProfileSaved, priority: "low" })
Допустимая функция основана на прототипе функции, используйте:
if (callback instanceof Function)
чтобы убедиться, что обратный вызов - это функция
источник
Если критерием для запуска обратного вызова является тот, определен он или нет, тогда все в порядке. Кроме того, я предлагаю дополнительно проверить, действительно ли это функция.
источник
Я перешел на кофейный скрипт и обнаружил, что аргументы по умолчанию - хороший способ решить эту проблему.
источник
Это легко сделать с помощью ArgueJS :
function save (){ arguments = __({callback: [Function]}) .....do stuff...... if(arguments.callback){ callback(); }; };
источник