Пишите повторно используемые функции как профессионал.

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

1. Определите, начинается ли строка с on

const onRE = /^on[^a-z]/;
const isOn = (key: string) => onRE.test(key);
console.log(isOn('onClick')); // true
console.log(isOn('onclick')); // false

Вы можете видеть, что он использует обычное сопоставление. Он будет соответствовать буквам, начинающимся с on и чьим следующим символом является не a до z.

2. Определение того, является ли свойство собственным

const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val: object, key: string | symbol): key is keyof typeof val =>
  hasOwnProperty.call(val, key);
const testObj = { name: 1 };
console.log(hasOwn(testObj, 'name')); // true
Object.getPrototypeOf(testObj).age = 2;
console.log(hasOwn(testObj, 'age')); // false

Этот метод использует Object.prototype.hasOwnProperty, чтобы определить, является ли ключ свойством самого объекта.

Когда мы используем Object.getPrototypeOf() для получения прототипа testObj и устанавливаем для него свойство age, hasOwn вернет false.

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

3. Определите, является ли это обещанием

const isObject = (val: unknown): val is Record<any, any> =>
  val !== null && typeof val === 'object';
const isFunction = (val: unknown): val is Function => typeof val === 'function';
const isPromise = <T = any>(val: unknown): val is Promise<T> => {
  return isObject(val) && isFunction(val.then) &&      isFunction(val.catch);
};
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(async function () {})); // false
console.log(isPromise(function* () {})); // false

Этот метод заимствует isObject, чтобы определить, что текущее значение является объектом, и isFunction, чтобы определить, что свойства then и catch текущего значения являются функциями.

Все три из них также используют ключевое слово is. Кроме того, isPromise также использует дженерики для передачи типа Result Promise.

4. Определите, является ли это целочисленной строкой

const isString = (val: unknown): val is string => typeof val === 'string';
const isIntegerKey = (key: unknown) =>
  isString(key) &&
  key !== 'NaN' &&
  key[0] !== '-' &&
  '' + parseInt(key, 10) === key;
console.log(isIntegerKey('10')); // true
console.log(isIntegerKey('010')); // false
console.log(isIntegerKey('3.0')); // false
console.log(isIntegerKey('Vue')); // false

Сначала используйте isString, чтобы определить, является ли это строковым типом, затем оцените, является ли это 'NaN', а первый символ не -, и, наконец, используйте пустую строку для преобразования десятичного числа, преобразованного с помощью parseInt, в строку, чтобы определить, равно ли оно исходная строка.

5. Результаты расчета строки кэша

const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {
  const cache: Record<string, string> = Object.create(null);
  return ((str: string) => {
    const hit = cache[str];
    return hit || (cache[str] = fn(str));
  }) as any;
};
const getUpperCase = cacheStringFunction((str: string): string =>
  str.toUpperCase(),
);
console.log(getUpperCase('a')); // A
console.log(getUpperCase('a')); // A

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

6. Дефис в CamelCase / CamelCase в дефис

const cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {
  const cache: Record<string, string> = Object.create(null);
  return ((str: string) => {
    const hit = cache[str];
    return hit || (cache[str] = fn(str));
  }) as any;
};
const camelizeRE = /-(\w)/g;
const camelize = cacheStringFunction((str: string): string => {
  return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
});
const hyphenateRE = /\B([A-Z])/g;
const hyphenate = cacheStringFunction((str: string) =>
  str.replace(hyphenateRE, '-$1').toLowerCase(),
);
console.log(camelize('on-click')); // onClick
console.log(camelize('test-a-click')); // testAClick
console.log(hyphenate('onClick')); // on-click
console.log(hyphenate('testAClick')); // test-a-click

Вышеупомянутые два метода используют регулярные выражения для сопоставления и используют String.prototype.replace() для замены символов, и они обертываются функцией кеша, представленной в предыдущем разделе, что означает, что когда одна и та же строка должна быть обработана, она будет непосредственно возвращена в кеш. Результаты.

7. Получить глобальный объект текущей среды

let _globalThis: any;
const getGlobalThis = (): any => {
  return (
    _globalThis ||
    (_globalThis =
      typeof globalThis !== 'undefined'
        ? globalThis
        : typeof self !== 'undefined'
        ? self
        : typeof window !== 'undefined'
        ? window
        : typeof global !== 'undefined'
        ? global
        : {})
  );
};
console.log(getGlobalThis());
console.log(getGlobalThis());

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

Давайте посмотрим на логику внутри функции, ее приоритет:

  1. Используйте globalThis, который обеспечивает стандартный способ доступа к глобальному объекту в разных средах.
  2. Судя по я, это потому, что в Веб-воркерах к оконному объекту нельзя получить доступ, а к текущему глобальному объекту можно получить доступ только через я.
  3. Общие оконные объекты.
  4. Глобальный объект в Node.js.

На сегодня все. Меня зовут Закари, и я буду продолжать публиковать истории, связанные с веб-разработкой. Если вам нравятся такие истории и вы хотите поддержать меня, рассмотрите возможность стать членом Medium. Это стоит 5 долларов в месяц и дает вам неограниченный доступ к контенту Medium. Я получу небольшую комиссию, если вы зарегистрируетесь по моей ссылке.

Ваша поддержка очень важна для меня — спасибо.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Присоединяйтесь к нашему сообществу Discord.