РЕДАКТИРОВАТЬ
Мне JSON.stringify
здесь не решение, так как это намного медленнее, чем рекурсия
JSON.stringify(fakeData)
.replace(/,/g, ';')
.replace(/:(?={)/g, '')
.replace(/"/g, '')
//Result
Recursion with reduce x 816,321 ops/sec ±7.38% (80 runs sampled)
JSON.stringify x 578,221 ops/sec ±1.72% (92 runs sampled)
Fastest is Recursion with reduce
Я делаю библиотеку css-in-js, и мне нужно использовать рекурсию, чтобы превратить объект в строку следующим образом:
Вход:
const fakeData = {
a: {
b: 'c',
d: 'e'
}
}
Вывод:
a{b:c;d:e;}
Моя функция рекурсии:
const buildKeyframe = (obj) => {
return Object.entries(obj).reduce((acc, [prop, value]) => {
if (typeof value === 'string') {
return `${acc}${prop}:${value};`
}
return `${acc}${prop}:{${buildKeyframe(value)}}`
}, '')
}
Эта функция работает, но я думаю, что есть возможности для улучшения (например, используйте TCO, избегайте использования reduce
) … Как мне написать лучшую функцию для рекурсии этой структуры данных?
1 ответ
Я согласен, что JSON.stringify не самый подходящий для этой проблемы не только потому, что он медленнее, но и потому, что его немного сложнее понять. И вы также правы, полагая, что reduce () — не лучший инструмент для этой работы. Использование .map () обеспечивает более естественное чтение.
const convert = obj => (
Object.entries(obj)
.map(([key, value]) => (
typeof value === 'string'
? `${key}:${value};`
: `${key}{${convert(value)}}`
))
.join('')
)
console.log(convert({
a: {
b: 'c',
d: 'e'
},
}))
При оптимизации подумайте о сценарии использования. Хотя рекурсия хвостового вызова может быть или не быть возможной, это сделает код намного более трудным для чтения, и это действительно не поможет. Основным преимуществом рекурсии хвостового вызова является экономия памяти в стеке вызовов и разрешение рекурсивной функции вызывать саму себя неограниченное количество раз, при этом в стеке используется только один кадр вызова. Не существует практического фрагмента чрезвычайно вложенного CSS, который можно было бы написать, чтобы оптимизация хвостового вызова того стоила.
В вашем вопросе скорость кажется одной из ваших основных проблем, но я немного поиграю в адвоката дьявола и спрошу, действительно ли это должно быть для этого варианта использования. Сколько CSS-in-JS вам нужно написать, прежде чем любое из этих улучшений микропроизводительности станет заметным? Десятки тысяч строк? Сотни тысяч? Я бы посоветовал сначала просто создать библиотеку, потом запустить несколько тестов и выяснить, какие ее части действительно работают медленно. Тогда беспокойтесь только об исправлении более медленных участков.