Вспомогательные функции JavaScript (новинка)

JavaScript опрос
Вспомогательные функции JavaScript (новинка)

предисловие

Источник вдохновения для письменных тестовых вопросов производителей первого уровня

содержание:

  • Часть 1: Массивы
  • Часть 2: Функции
  • Часть 3: Струны
  • Часть 4: Объекты
  • Часть 5: Числа
  • Часть VI: Работа в браузере и прочее

Отфильтровано из следующих двух статей:

Изначально я просто хотел отфильтровать вышеприведенную статью, но после упрощения некоторых избыточных и бесполезных функций инструмента я почувствовал, что этого недостаточно. Так что я пошел по лозе и нашел оригинальный адрес:30 seconds of code

Затем я прочитал все фрагменты кода, просмотрев следующие более 100 фрагментов кода и добавил кое-что из своего собственного понимания.Кроме того,Названия функций инструмента в этой статье очень достойны внимания.

1. Часть 1: Массивы

1. all: Булево суждение о конгруэнтности

const all = (arr, fn = Boolean) => arr.every(fn);

all([4, 2, 3], x => x > 1); // true
all([1, 2, 3]); // true

2. allEqual: проверить, что элементы массива равны

const allEqual = arr => arr.every(val => val === arr[0]);

allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true

3. approximatelyEqual: примерно равно

const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;

approximatelyEqual(Math.PI / 2.0, 1.5708); // true

4. arrayToCSV: Поворот массиваCSVформат (строка с пробелами)


const arrayToCSV = (arr, delimiter = ',') =>
  arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
  
arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'

5. arrayToHtmlList: Поворот массиваliсписок

Этот фрагмент кода преобразует элементы массива в<li>label и добавьте его в список с заданным идентификатором.

const arrayToHtmlList = (arr, listID) =>
  (el => (
    (el = document.querySelector('#' + listID)),
    (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
  ))();
  
arrayToHtmlList(['item 1', 'item 2'], 'myListID');

6. average: Средний

const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
average(...[1, 2, 3]); // 2
average(1, 2, 3); // 2

7. averageBy: Среднее значение свойства объекта массива

Этот фрагмент кода получит среднее значение свойств объекта массива.

const averageBy = (arr, fn) =>
  arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
  arr.length;
  
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5

8. bifurcate: разделить массив после утверждения

В зависимости от значения, возвращаемого каждым элементом, используйтеreduce() а такжеpush()добавить элемент во второй параметрfnсередина .

const bifurcate = (arr, filter) =>
  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); 
// [ ['beep', 'boop', 'bar'], ['foo'] ]

9. castArray: Преобразование других типов в массивы

const castArray = val => (Array.isArray(val) ? val : [val]);

castArray('foo'); // ['foo']
castArray([1]); // [1]
castArray(1); // [1]

10. compact: удалить недопустимые/бесполезные значения из массива

const compact = arr => arr.filter(Boolean);

compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]); 
// [ 1, 2, 3, 'a', 's', 34 ]

11. countOccurrences: Количество вхождений обнаруженных значений

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3

12. deepFlatten: рекурсивно сгладить массив

const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));

deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]

13. difference: находит различия (и возвращает уникальность для первого массива)

Этот фрагмент кода находит разницу между двумя массивами и возвращает то, что уникально для первого массива.


const difference = (a, b) => {
  const s = new Set(b);
  return a.filter(x => !s.has(x));
};

difference([1, 2, 3], [1, 2, 4]); // [3]

14. differenceBy: Первое исполнение снова ищет различия

Этот метод возвращает разницу между двумя массивами после применения данной функции к каждому элементу двух списков.

const differenceBy = (a, b, fn) => {
  const s = new Set(b.map(fn));
  return a.filter(x => !s.has(fn(x)));
};

differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ]

15. dropWhile: удалить значения, не соответствующие критериям

Этот фрагмент удаляет элементы из верхней части массива до тех пор, пока переданная функция не вернется какtrue.

const dropWhile = (arr, func) => {
  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
  return arr;
};

dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]

16. flatten: сглаженный массив с указанной глубиной

Второй параметр этого фрагмента указывает глубину.

const flatten = (arr, depth = 1) =>
  arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);

flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]

17. indexOfAll: возвращает все индексы значения в массиве

Этот фрагмент кода можно использовать для получения всех индексов значения в массиве или возврата пустого массива, если значение не включено в это значение.

const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);

indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []

18. intersection: пересечение двух массивов


const intersection = (a, b) => {
  const s = new Set(b);
  return a.filter(x => s.has(x));
};

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]

19. intersectionWith: пересечение двух массивов, удовлетворяющих условиям

Этот фрагмент можно использовать для возврата списка элементов, присутствующих в обоих массивах, после того, как функция была выполнена для каждого элемента двух массивов.


const intersectionBy = (a, b, fn) => {
  const s = new Set(b.map(fn));
  return a.filter(x => s.has(fn(x)));
};

intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]

20. intersectionWith: сначала сравнить, а затем вернуть пересечение

const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);

intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]

21. minN: возвращает возрастающий массив указанной длины

const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);

minN([1, 2, 3]); // [1]
minN([1, 2, 3], 2); // [1,2]

22. negate: Обратный фильтр на основе условий


const negate = func => (...args) => !func(...args);

[1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]

23. randomIntArrayInRange: Создать случайный массив заданной длины между двумя числами.

const randomIntArrayInRange = (min, max, n = 1) =>
  Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
  
randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]

24. sample: Получить случайные числа в указанном массиве

const sample = arr => arr[Math.floor(Math.random() * arr.length)];

sample([3, 7, 9, 11]); // 9

25. sampleSize: Получить случайное число указанной длины в указанном массиве

Этот фрагмент кода можно использовать для получения случайных чисел заданной длины из массива до тех пор, пока массив не будет исчерпан.использоватьFisher-YatesАлгоритм случайным образом выбирает элементы в массиве.

const sampleSize = ([...arr], n = 1) => {
  let m = arr.length;
  while (m) {
    const i = Math.floor(Math.random() * m--);
    [arr[m], arr[i]] = [arr[i], arr[m]];
  }
  return arr.slice(0, n);
};

sampleSize([1, 2, 3], 2); // [3,1]
sampleSize([1, 2, 3], 4); // [2,3,1]

26. shuffle: "перетасовать" массив

Этот фрагмент кода используетFisher-YatesАлгоритм случайным образом сортирует элементы массива.


const shuffle = ([...arr]) => {
  let m = arr.length;
  while (m) {
    const i = Math.floor(Math.random() * m--);
    [arr[m], arr[i]] = [arr[i], arr[m]];
  }
  return arr;
};

const foo = [1, 2, 3];
shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]

27. nest:согласно сparent_idСтруктура связующего дерева (Али односторонний Женти)

согласно каждомуparent_id, который создает определенный объект с древовидной структурой.

const nest = (items, id = null, link = 'parent_id') =>
  items
    .filter(item => item[link] === id)
    .map(item => ({ ...item, children: nest(items, item.id) }));

Применение:

const comments = [
  { id: 1, parent_id: null },
  { id: 2, parent_id: 1 },
  { id: 3, parent_id: 1 },
  { id: 4, parent_id: 2 },
  { id: 5, parent_id: 4 }
];
const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }]

Настоятельно рекомендуется разобраться в реализации этого, потому что это реальная проблема Али, с которой я столкнулся лично:

2. Часть 2: Функции

1. attempt: Исключения функции перехвата

Этот фрагмент кода выполняет функцию, которая возвращает результат или объект обнаруженной ошибки.

onst attempt = (fn, ...args) => {
  try {
    return fn(...args);
  } catch (e) {
    return e instanceof Error ? e : new Error(e);
  }
};
var elements = attempt(function(selector) {
  return document.querySelectorAll(selector);
}, '>_>');
if (elements instanceof Error) elements = []; // elements = []

2. defer: отложить выполнение

Этот фрагмент кода задерживает выполнение функции до тех пор, пока текущий стек вызовов не будет очищен.

const defer = (fn, ...args) => setTimeout(fn, 1, ...args);

defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'

3. runPromisesInSeries: запустить несколькоPromises

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
const delay = d => new Promise(r => setTimeout(r, d));

runPromisesInSeries([() => delay(1000), () => delay(2000)]);
//依次执行每个Promises ,总共需要3秒钟才能完成

4. timeTaken: вычислить время выполнения функции


const timeTaken = callback => {
  console.time('timeTaken');
  const r = callback();
  console.timeEnd('timeTaken');
  return r;
};

timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms

5. createEventHub: Простой шаблон публикации/подписки.

Создайте концентратор событий публикации/подписки (pub-sub) сemit,onа такжеoffметод.

  1. использоватьObject.create(null)создать пустойhubобъект.
  2. emit,согласно сeventмассив обработчиков разрешения аргументов, затем.forEach()Запустите каждый обработчик, передав данные в качестве параметра.
  3. on, создайте массив для событий (или пустой массив, если они не существуют), затем.push()Добавьте обработчики в этот массив.
  4. off,использовать.findIndex()Найдите индекс обработчика в массиве событий и используйте.splice()удалять.
const createEventHub = () => ({
  hub: Object.create(null),
  emit(event, data) {
    (this.hub[event] || []).forEach(handler => handler(data));
  },
  on(event, handler) {
    if (!this.hub[event]) this.hub[event] = [];
    this.hub[event].push(handler);
  },
  off(event, handler) {
    const i = (this.hub[event] || []).findIndex(h => h === handler);
    if (i > -1) this.hub[event].splice(i, 1);
    if (this.hub[event].length === 0) delete this.hub[event];
  }
});

Применение:

const handler = data => console.log(data);
const hub = createEventHub();
let increment = 0;

// 订阅,监听不同事件
hub.on('message', handler);
hub.on('message', () => console.log('Message event fired'));
hub.on('increment', () => increment++);

// 发布:发出事件以调用所有订阅给它们的处理程序,并将数据作为参数传递给它们
hub.emit('message', 'hello world'); // 打印 'hello world' 和 'Message event fired'
hub.emit('message', { hello: 'world' }); // 打印 对象 和 'Message event fired'
hub.emit('increment'); // increment = 1

// 停止订阅
hub.off('message', handler);

6. memoize: функция кэширования

путем создания экземпляраMapобъект для создания пустого кеша.

Возвращает функцию, которая хранит аргумент, который будет предоставлен мемоизированной функции, проверяя, кэшируется ли вывод функции входного значения; если нет, сохраняет и возвращает его.

const memoize = fn => {
  const cache = new Map();
  const cached = function(val) {
    return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
  };
  cached.cache = cache;
  return cached;
};

Ps: Эта версия может быть не очень понятной, есть также исходная версия Vue:

/**
 * Create a cached version of a pure function.
 */
export function cached<F: Function> (fn: F): F {
  const cache = Object.create(null)
  return (function cachedFn (str: string) {
    const hit = cache[str]
    return hit || (cache[str] = fn(str))
  }: any)
}

7. once: функция, которая вызывается только один раз

const once = fn => {
  let called = false
  return function () {
    if (!called) {
      called = true
      fn.apply(this, arguments)
    }
  }
};

Применение:

const startApp = function(event) {
  console.log(this, event); // document.body, MouseEvent
};
document.body.addEventListener('click', once(startApp)); // 只执行一次startApp

8. flattenObject: сгладить объект с путем к ключу

Используйте рекурсию.

  1. использоватьObject.keys(obj)соединениеArray.prototype.reduce(), преобразуйте каждый конечный узел в узел плоского пути.
  2. Если значением ключа является объект, функция вызывает себя с соответствующимprefixсоздать путьObject.assign().
  3. В противном случае к объекту-аккумулятору добавляется соответствующая пара "ключ-значение" префикса.
  4. prefixВторой параметр всегда следует опускать, если вы не хотите, чтобы каждая клавиша имела префикс.
const flattenObject = (obj, prefix = '') =>
  Object.keys(obj).reduce((acc, k) => {
    const pre = prefix.length ? prefix + '.' : '';
    if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
    else acc[pre + k] = obj[k];
    return acc;
  }, {});
  
flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 }

9. unflattenObject: Развернуть объект по пути ключа

Вопреки вышесказанному, разверните объект.

const unflattenObject = obj =>
  Object.keys(obj).reduce((acc, k) => {
    if (k.indexOf('.') !== -1) {
      const keys = k.split('.');
      Object.assign(
        acc,
        JSON.parse(
          '{' +
            keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
            obj[k] +
            '}'.repeat(keys.length)
        )
      );
    } else acc[k] = obj[k];
    return acc;
  }, {});
  
unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 }

Использование этого, делаяTreeОчень удобно брать значения в компонентах или сложных формах.

3. Часть 3: Струны

1.byteSize: возвращает длину строки в байтах.

const byteSize = str => new Blob([str]).size;

byteSize('😀'); // 4
byteSize('Hello World'); // 11

2. capitalize: Сделать первую букву заглавной

const capitalize = ([first, ...rest]) =>
  first.toUpperCase() + rest.join('');
  
capitalize('fooBar'); // 'FooBar'
capitalize('fooBar', true); // 'Foobar'

3. capitalizeEveryWord: Сделать заглавной первую букву каждого слова.

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());

capitalizeEveryWord('hello world!'); // 'Hello World!'

4. decapitalize: строчная первая буква

const decapitalize = ([first, ...rest]) =>
  first.toLowerCase() + rest.join('')

decapitalize('FooBar'); // 'fooBar'
decapitalize('FooBar'); // 'fooBar'

5. luhnCheck: Проверка номера банковской карты (luhnалгоритм)

LuhnРеализация алгоритма проверки различных идентификационных номеров, таких как номера кредитных карт, номера IMEI, идентификационные номера национальных провайдеров и т. д.

а такжеString.prototype.split('')Используется в комбинации для получения массива чисел. чтобы получить последний номер. воплощать в жизньluhnалгоритм. Возврат, если делится, иначе возврат.

const luhnCheck = num => {
  let arr = (num + '')
    .split('')
    .reverse()
    .map(x => parseInt(x));
  let lastDigit = arr.splice(0, 1)[0];
  let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0);
  sum += lastDigit;
  return sum % 10 === 0;
};

Пример:

luhnCheck('4485275742308327'); // true
luhnCheck(6011329933655299); //  false
luhnCheck(123456789); // false

Пополнить:Правила проверки номера банковской карты:

оluhnАлгоритмы, вы можете обратиться к следующим статьям:

Алгоритм проверки номера банковской карты (алгоритм Луна, также известный как алгоритм по модулю 10)

Проверка номера банковской карты принимаетLuhnАлгоритм процесса проверки примерно такой:

  1. Пронумеруйте строку номера карты справа налево, самая правая первая цифра - 1, самая правая вторая цифра - 2, самая правая третья цифра - 3....

  2. Пройдите справа налево, выполните третий шаг для каждого символа t и сложите результаты вычисления каждого бита, чтобы получить число s.

  3. Правило расчета для каждого бита: если бит нечетный, вернуть сам t, если четный бит, сначала умножить t на 2, чтобы получить число n, если n однозначное число ( меньше 10), напрямую верните n, в противном случае добавьте единицы и десятки цифр n и верните его.

  4. Если s делится на 10, число допустимо, в противном случае число неверно.

Поскольку для окончательного результата потребуется остаток от 10, чтобы определить, делится ли он на 10, поэтому его также называют алгоритмом по модулю 10.

Конечно, библиотека ароматнее:bankcardinfo

6. splitLines: Разбить многострочную строку на массив строк.

использоватьString.prototype.split()и регулярное выражение для соответствия новым строкам и создания массива.

const splitLines = str => str.split(/\r?\n/);

splitLines('This\nis a\nmultiline\nstring.\n'); // ['This', 'is a', 'multiline', 'string.' , '']

7. stripHTMLTags: удалить строкуHTMlЭтикетка

удалить из строкиHTML / XMLЭтикетка.

Удалить из строки с помощью регулярного выраженияHTML / XMLотметка.

const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');

stripHTMLTags('<p><em>lorem</em> <strong>ipsum</strong></p>'); // 'lorem ipsum'

4. Часть 4: Объекты

1. dayOfYear: Дни текущей даты

const dayOfYear = date =>
  Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);

dayOfYear(new Date()); // 285

2. forOwn: перебирать свойства и выполнять обратные вызовы

const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1

3. Get Time From Date: строка, которая возвращает текущее время в 24-часовом формате.

const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);

getColonTimeFromDate(new Date()); // "08:38:00"

4. Get Days Between Dates: возвращает количество дней в периоде даты.

const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
  (dateFinal - dateInitial) / (1000 * 3600 * 24);
  
getDaysDiffBetweenDates(new Date('2019-01-01'), new Date('2019-10-14')); // 286

5. is: Проверяет, относится ли значение к определенному типу.

const is = (type, val) => ![, null].includes(val) && val.constructor === type;

is(Array, [1]); // true
is(ArrayBuffer, new ArrayBuffer()); // true
is(Map, new Map()); // true
is(RegExp, /./g); // true
is(Set, new Set()); // true
is(WeakMap, new WeakMap()); // true
is(WeakSet, new WeakSet()); // true
is(String, ''); // true
is(String, new String('')); // true
is(Number, 1); // true
is(Number, new Number(1)); // true
is(Boolean, true); // true
is(Boolean, new Boolean(true)); // true

6. isAfterDate: проверить, если после определенной даты

const isAfterDate = (dateA, dateB) => dateA > dateB;

isAfterDate(new Date(2010, 10, 21), new Date(2010, 10, 20)); // true

7. isBeforeDate: проверить, не раньше ли определенной даты

const isBeforeDate = (dateA, dateB) => dateA < dateB;

isBeforeDate(new Date(2010, 10, 20), new Date(2010, 10, 21)); // true

8 tomorrow: Получить завтрашнее время в строковом формате.


const tomorrow = () => {
  let t = new Date();
  t.setDate(t.getDate() + 1);
  return t.toISOString().split('T')[0];
};

tomorrow(); // 2019-10-15 (如果明天是2019-10-15)

9. equals: суждение о конгруэнтности

Глубокое сравнение проводится между двумя переменными, чтобы определить, конгруэнтны ли они.

Суть этого сокращения фрагментов кода заключается в том, чтоArray.prototype.every()использование.

const equals = (a, b) => {
  if (a === b) return true;
  if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
  if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
  if (a.prototype !== b.prototype) return false;
  let keys = Object.keys(a);
  if (keys.length !== Object.keys(b).length) return false;
  return keys.every(k => equals(a[k], b[k]));
};

Применение:

equals({ a: [2, { e: 3 }], b: [4], c: 'foo' }, { a: [2, { e: 3 }], b: [4], c: 'foo' }); // true

5. Часть 5: Числа

1. randomIntegerInRange: генерировать случайные целые числа в указанном диапазоне

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

randomIntegerInRange(0, 5); // 3

2. randomNumberInRange: генерировать случайные десятичные дроби в указанном диапазоне.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;

randomNumberInRange(2, 10); // 6.0211363285087005

3. round: округлить до указанного количества цифр

const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);

round(1.005, 2); // 1.01

4. sum: вычислить сумму массива или нескольких чисел.


const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);

sum(1, 2, 3, 4); // 10
sum(...[1, 2, 3, 4]); // 10

5. toCurrency: простая конвертация валюты

const toCurrency = (n, curr, LanguageFormat = undefined) =>
  Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
  
toCurrency(123456.789, 'EUR'); // €123,456.79
toCurrency(123456.789, 'USD', 'en-us'); // $123,456.79  
toCurrency(123456.789, 'USD', 'fa'); // ۱۲۳٬۴۵۶٫۷۹
toCurrency(322342436423.2435, 'JPY'); // ¥322,342,436,423 

6. Часть VI: Работа в браузере и прочее

1. bottomVisible: проверьте, виден ли низ страницы

const bottomVisible = () =>
  document.documentElement.clientHeight + window.scrollY >=
  (document.documentElement.scrollHeight || document.documentElement.clientHeight);

bottomVisible(); // true

2. Create Directory: проверить создать каталог

Этот фрагмент кода вызываетfsмодульныйexistsSync()Проверьте, существует ли каталог, если нет, тоmkdirSync()Создайте этот каталог.

const fs = require('fs');
const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);
createDirIfNotExists('test'); 

3. currentURL: вернуться к текущей ссылкеurl

const currentURL = () => window.location.href;

currentURL(); // 'https://juejin.cn'

4. distance: возвращает расстояние между двумя точками

Этот фрагмент кода возвращает расстояние между двумя точками путем вычисления евклидова расстояния.

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);

distance(1, 1, 2, 3); // 2.23606797749979

5. elementContains: проверьте, содержит ли он дочерние элементы

Этот фрагмент кода проверяет, содержит ли родительский элемент дочерние элементы.

const elementContains = (parent, child) => parent !== child && parent.contains(child);

elementContains(document.querySelector('head'), document.querySelector('title')); // true
elementContains(document.querySelector('body'), document.querySelector('body')); // false

6. getStyle: возвращает эффективный стиль указанного элемента.

const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];

getStyle(document.querySelector('p'), 'font-size'); // '16px'

7. getType: имя типа возвращаемого значения или переменной

const getType = v =>
  v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
  
getType(new Set([1, 2, 3])); // 'set'
getType([1, 2, 3]); // 'array'

8. hasClass: проверить имя класса указанного элемента

const hasClass = (el, className) => el.classList.contains(className);
hasClass(document.querySelector('p.special'), 'special'); // true

9. hide: скрыть все указанные теги

const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));

hide(document.querySelectorAll('img')); // 隐藏所有<img>标签

10. httpsRedirect:HTTPПрыгатьHTTPS

const httpsRedirect = () => {
  if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
};

httpsRedirect(); // 若在`http://www.baidu.com`, 则跳转到`https://www.baidu.com`

11. insertAfter: вставляет новый элемент после указанного элемента

const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);

// <div id="myId">...</div> <p>after</p>
insertAfter(document.getElementById('myId'), '<p>after</p>'); 

12. insertBefore: вставляет новый элемент перед указанным элементом

const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);

insertBefore(document.getElementById('myId'), '<p>before</p>'); // <p>before</p> <div id="myId">...</div>

13. isBrowser: проверьте, является ли это средой браузера.

Этот фрагмент можно использовать, чтобы определить, является ли текущая среда выполнения браузером. Это помогает избежать ошибок при запуске модулей интерфейса на сервере (узле).

const isBrowser = () => ![typeof window, typeof document].includes('undefined');

isBrowser(); // true (browser)
isBrowser(); // false (Node)

14. isBrowserTab: проверьте, активна ли текущая вкладка.

const isBrowserTabFocused = () => !document.hidden;

isBrowserTabFocused(); // true

15. nodeListToArray: КонвертироватьnodeListкак массив

const nodeListToArray = nodeList => [...nodeList];

nodeListToArray(document.childNodes); // [ <!DOCTYPE html>, html ]

16. Random Hexadecimal Color Code: случайный шестнадцатеричный цвет


const randomHexColorCode = () => {
  let n = (Math.random() * 0xfffff * 1000000).toString(16);
  return '#' + n.slice(0, 6);
};

randomHexColorCode(); // "#e34155"

17. scrollToTop: Плавная прокрутка вверх

Этот фрагмент кода можно использовать для плавной прокрутки вверх текущей страницы.

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};

scrollToTop();

18. smoothScroll: прокрутка до указанной области элемента

Этот фрагмент кода плавно прокручивает указанный элемент в видимую область окна браузера.

const smoothScroll = element =>
  document.querySelector(element).scrollIntoView({
    behavior: 'smooth'
  });
  
smoothScroll('#fooBar'); 
smoothScroll('.fooBar'); 

19. detectDeviceType: Обнаружение мобильных устройств/ПК.

const detectDeviceType = () =>
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    ? 'Mobile'
    : 'Desktop';

20. getScrollPosition: возвращает текущую позицию прокрутки

Параметр по умолчаниюwindow,pageXOffset(pageYOffset)это первый выбор, если нет, используйтеscrollLeft(scrollTop)

const getScrollPosition = (el = window) => ({
  x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
  y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});

getScrollPosition(); // {x: 0, y: 200}

21. size: Получить длину байтов переменных разных типов

Эта реализация очень умная, используяBlobСвойство файлового объекта для получения длины объекта.

Кроме того, множественный тернарный оператор действительно ароматный.

const size = val =>
  Array.isArray(val)
    ? val.length
    : val && typeof val === 'object'
    ? val.size || val.length || Object.keys(val).length
    : typeof val === 'string'
    ? new Blob([val]).size
    : 0;

size([1, 2, 3, 4, 5]); // 5
size('size'); // 4
size({ one: 1, two: 2, three: 3 }); // 3

22. escapeHTML: побегHTML

Конечно, для предотвращенияXSSАтакуйте.

const escapeHTML = str =>
  str.replace(
    /[&<>'"]/g,
    tag =>
      ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;',
        '"': '&quot;'
      }[tag] || tag)
  );

escapeHTML('<a href="#">Me & you</a>'); // '&lt;a href=&quot;#&quot;&gt;Me &amp; you&lt;/a&gt;'

❤️ После прочтения трех вещей

Если вы найдете этот контент вдохновляющим, я хотел бы пригласить вас сделать мне три небольших одолжения:

  1. Ставьте лайк, чтобы больше людей увидело этот контент
  2. Обратите внимание на паблик «Учитель фронтенд-убеждения», и время от времени делитесь оригинальными знаниями.
  3. Также смотрите другие статьи

Вы также можете прийти ко мнеGitHubПолучите исходные файлы всех статей в блоге:

Руководство по убеждению:GitHub.com/Roger-Hi RO/…