voraa, не согласен на счёт (object, options, filter). В options нормальные умолчания.)
Правилбьно было бы конечно, чтоб и так (object, options, filter) и так (object, filter, options). Но это некрасивую условную раскоряку писать.) Давно хочу либу сделать для работы с аргументами функции в любых порядках и направлениях, да руки не доходят. Те что видел в npm мне эстетически не нравятся.) |
Цитата:
Простой пример - функция создания элемента С вариантами использования create (tag, options [, children [, parent]]) create (tag [, children | null [, parent]]) где tag - string children - Node | Array | string parent - Element options - object (но не Array | Node) Слишком много разных проверок, что бы просто создать элемент Проще зафиксировать параметры и проверять на null или undefined. Универсализм плохо сочетается с эффективностью. |
voraa, я это себе как-то так представляю(чисто черновой набросок):
function create ({tag, options, children, parent}) { console.log({tag, options, children, parent}) } function isType(arg, types) { if(Array.isArray(types)) return types.some(type => isType(arg, type)); if(typeof types === 'function') return types(arg); return arg === types; } function findArgs(args, list) { let maxArgsMatchLength = -1; let maxArgsMatchNames; list.forEach(({ sublist, sublist: { length }, names }) => { if(length <= maxArgsMatchLength) return; // ничего не делаем если уже нашли больше аргументов for(let i = length; i--;) { if(!isType(args[i], sublist[i])) return false; } maxArgsMatchLength = length; maxArgsMatchNames = names; }); if(maxArgsMatchLength === -1) throw new Error('invalid arguments'); return Object.fromEntries( maxArgsMatchNames .slice(0, maxArgsMatchLength) .map((key, i) => [key, args[i]]) ) } function withAttrs(func, list) { const bigList = list.flatMap(obj => { const sublist = []; const entries = Object.entries(obj); const current = []; const names = []; for(let arg in obj) { const type = obj[arg]; if(arg.endsWith('?')) { arg = arg.slice(0, -1); sublist.push(current.slice()); } names.push(arg); current.push(type) } sublist.push(current); return sublist.map(arr => ({ sublist: arr, names })); }) return function(...args) { return func.call(this, findArgs(args, bigList)); } } isNode = () => true; createWithArgs = withAttrs(create, [ {tag: isString, options: isPlainObject, 'children?': [isNode, isArray, isString], 'parent?': isElement}, {tag: isString, 'children?': [isNode, isArray, isString, null], 'parent?': isElement}, ]); createWithArgs('1', {a: 3}, []) Все isX функции из lodash, но естественно возможно использование своих. +Обязательно должно бы кэширование: чтоб одна функция проверки типа вызывалась для одного конкретного аргумента только один раз. +Разделить проверку списка аргументов не всех сразу, а по порядку. +Добавить поддержку spread. +Типизировать для typescript(это будет ад, если вообще возможно). ... =) |
Это конечно жесть и ад.
Я плюнул на такие вещи. Если и делаю, то для конкретной функции и в случаях, когда просто можно сдвигать параметры влево |
Все это называется код ради кода.
Если вы это используете то у вас ошибки в архитектуре, голове ... |
Vlasenko Fedor,
Цитата:
Цитата:
Просто иногда пишешь функцию с чётким интерфейсом, а мыслишка в голове "а ведь было бы круто если бы можно было и так, и вот так, и ещё так и чтоб TS сам на это overload'ы вывел".) С TS кстати это не настолько ужасно, как может показаться: он должен проверять как возможные комбинации аргументов относительно переданной функции, так и делать чёткий интерфейс для новой. Т.е. тут нельзя будет опечататься или указать что-то не то. Как вариант обёртки для внешнего интерфейса какой-нить либы - почему нет.) |
Цитата:
мне кажется так достаточно для парметров const test = (tag, params = {}) => { const def = { a: 'text', b: 2 } params = { ...def, ...params } console.log(params) } test('tag', { b: 5, c: 3 }) без использования TS, глянув дефолтные всегда можно понять, что передать TS не учу, я им vbs, vb не могу простить только подумал MS продуктами уже 12 лет как и не пользуюсь и вроде ок :) |
Aetae,
Для ускорения строку 21 наверно можно так if (length != args.length) return; |
voraa, не, мыж не знаем что там за проверки, может ему ок, если последние аргументы будут undefined:
{foo: isString, bar: [isArray, undefined], 'buz': [isElement, undefined]}, По идее конечно в таком случае надо юзать 'foo?' но мало ли какие там сложные и хитрые проверки будут.) |
По идее
('str') и ('str', undefined, undefined) - разные вещи. В последнем случае количество аргументов будет 3 и проверка нормально сработает ЗЫ Я так нарвался на scrollIntoView() у меня там вызов получался scrollIntoView(x), а x было = undefined И долго чесал репу, почему не работает, как надо |
Часовой пояс GMT +3, время: 19:04. |