<h1 class="header">click me</h1>
<h1 class="header">click me</h1>
<h1 class="header">click me</h1>
const text = [ 'hello, world!!', 'fuck the world', 'fuck everything' ];
$('.header').click(function() {
const index = $(this).data('index') || 0;
$(this).text(text[index]).data('index', (index + 1) % text.length);
});
const findPath = (obj, val) =>
obj === val
? []
: Object.entries(obj instanceof Object ? obj : {}).reduce((found, n) => (
found || ((found = findPath(n[1], val)) && found.unshift(n[0])),
found
), null);
function findPath(obj, val) {
for (const stack = [ [ obj, [] ] ]; stack.length;) {
const [ n, keys ] = stack.pop();
if (Object.is(n, val)) {
return keys;
} else if (n instanceof Object) {
stack.push(...Object.entries(n).map(([ k, v ]) => [ v, [ ...keys, k ] ]));
}
}
return null;
}
setInterval($items => {
$items.each(i => $items.eq(i).css({
left: `${Math.random() * window.innerWidth}px`,
top: `${Math.random() * window.innerHeight}px`,
}));
}, 500, $элементыКоторымНадоЗадаватьСлучайныеКоординаты);
const formTemplate = `<здесь html-код формы>`;
$(document).on('change', 'селектор чекбокса', function() {
const $el = $(this).closest('селектор формы');
if (this.checked) {
$el.after(formTemplate);
} else {
$el.nextAll('селектор формы').remove();
}
});
const group = (arr, keyProp, childrenProp) =>
Object.values(arr.reduce((acc, { [childrenProp]: children, ...n }) => {
const item = acc[n[keyProp]] = acc[n[keyProp]] || n;
if (children) {
children = (item.childItems || []).concat(children);
item[childrenProp] = group(children, keyProp, childrenProp);
}
return acc;
}, {}));
const grouped = group(products, 'name', 'childItems');
switch (true) {
case one.includes(inp):
...
break;
case two.includes(inp):
...
break;
}
const arr = [
{
values: [ ... ],
action: () => { ... },
},
{
values: [ ... ],
action: () => { ... },
},
];
arr.find(n => n.values.includes(inp))?.action();
str.split('"').filter((n, i) => i & 1)
// или
str.match(/".*?"/g)?.map(n => n.slice(1, -1)) ?? []
// или
Array.from(str.matchAll(/"([^"]*)"/g), n => n[1])
// или
Array.prototype.reduce.call(str, (acc, n) => {
if (n !== '"') {
acc[1]?.push(n);
} else if (acc[1]) {
acc[0].push(acc[1].join(''));
acc[1] = null;
} else {
acc[1] = [];
}
return acc;
}, [ [], null ])[0]
const result = arr1.map((n, i) => {
const index = Math.min(i * 2, ((arr2.length - 2) / 2 | 0) * 2);
return `name: ${n} val1: ${arr2[index]} val2: ${arr2[index + 1]}`;
});
result.forEach(alert);
arr.reduce((acc, n, i) => (
(i && (acc[acc.length - 1].length + !(acc.length & 1) !== 3)) || acc.push([]),
acc[acc.length - 1].push(n),
acc
), [])
const className = 'text';
.{ старый_текст: новый_текст }
:const months = Object.fromEntries(Array.from({ length: 12 }, (n, i) => {
const d = new Date(0, i);
return [
d.toLocaleString('en-US', { month: 'long' }),
d.toLocaleString('ru-RU', { month: 'long' }).replace(/./, m => m.toUpperCase()),
];
}));
$('.' + className).text((i, text) => months[text.trim()]);
// или
document.querySelectorAll(`.${className}`).forEach(n => {
const key = n.innerText;
if (months.hasOwnProperty(key)) {
n.innerText = months[key];
}
});
// или
for (const n of document.getElementsByClassName(className)) {
n.textContent = months[n.textContent.trim()] ?? n.textContent;
}
document.querySelector('table').addEventListener('input', e => {
const tr = e.target.closest('tr');
const price = parseInt(tr.querySelector('.price').innerText);
const value = e.target.value;
tr.querySelector('.item_result').innerText = value * price;
});
function groupNames(arr) {
const tree = Object.fromEntries(arr.map(n => [ n.categoryId, { ...n, children: [] } ]));
const values = Object.values(tree);
const getNames = ({ name, children }) => children.length
? children.reduce((acc, n) => (
acc.push(...getNames(n).map(m => [ name, ...m ])),
acc
), [])
: [ [ name ] ];
values.forEach(n => tree[n.parentCategoryId]?.children.push(n));
return values
.filter(n => !n.parentCategoryId)
.flatMap(n => getNames(n).map(n => n.join(' - ')));
}
forEach
и for...of
. Откройте документацию и разберитесь.forEach
нельзя прервать (throw
не в счёт), в то время как в теле for...of
можно использовать break
и return
(да, в forEach
тоже можно использовать return
, но эффект будет не тот - уход на следующую итерацию, т.е., то же, что и continue
для for...of
).forEach
можно назначать контекст выполнения (через второй параметр, коллбек при этом не должен быть стрелочной функцией).forEach
отложить запуск следующей итерации до окончания выполнения асинхронных операций, запущенных в текущей итерации. В случае for...of
можно добавить async
в объявление функции, внутри которой он находится, и использовать await
.Symbol.iterator
, то это ещё не означает, что и forEach
там тоже присутствует. Впрочем, тут могут быть варианты одолжить чужой forEach
:Array.prototype.forEach.call('ABC', alert);
NodeList.prototype.forEach.call(document.scripts, console.log);
$('.button').click(function() {
const val = +$('.value').text((i, text) => +text + 1).text();
$('.item')
.removeClass('xxx')
.filter((i, el) => +$(el).text() <= val)
.sort((a, b) => $(a).text() - $(b).text())
.last()
.addClass('xxx');
});
document.querySelector('.button').addEventListener('click', () => {
const val = ++document.querySelector('.value').innerText;
const items = Array.from(document.querySelectorAll('.item'), n => [ n, +n.innerText ]);
const max = items.reduce((max, n) => n[1] <= val && n[1] > max ? n[1] : max, -Infinity);
items.forEach(n => n[0].classList.toggle('xxx', n[1] === max));
});