• JavaScript 工具函数大全


    前言

    一线大厂笔试题灵感来源

    目录:

    • 第一部分:数组

    • 第二部分:函数

    • 第三部分:字符串

    • 第四部分:对象

    • 第五部分:数字

    • 第六部分:浏览器操作及其它

    筛选自以下两篇文章:

    • 《127 Helpful JavaScript Snippets You Can Learn in 30 Seconds or Less》

    • 《30 seconds of code》

    原本只想筛选下上面的那篇文章,在精简掉了部分多余且无用的代码片段后,感觉不够。于是顺藤摸瓜,找到了原地址:30 seconds of code

    然后将所有代码段都看了遍,筛选了以下一百多段代码片段,并加入了部分自己的理解。


    另外,本文工具函数的命名非常值得借鉴。

    1. 第一部分:数组

    1. `all`:布尔全等判断

    1. const all = (arr, fn = Boolean) => arr.every(fn);
    2. all([423], x => x > 1); // true
    3. all([123]); // true

    2. `allEqual`:检查数组各项相等

    1. const allEqual = arr => arr.every(val => val === arr[0]);
    2. allEqual([123456]); // false
    3. allEqual([1111]); // true

    3.`approximatelyEqual`:约等于

    1. const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    2. approximatelyEqual(Math.PI / 2.0, 1.5708); /true

    4.`arrayToCSV`:数组转`CSV`格式(带空格的字符串)

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

    5.`arrayToHtmlList`:数组转`li`列表

    此代码段将数组的元素转换为

  • 标签,并将其附加到给定ID的列表中。

    1. const arrayToHtmlList = (arr, listID) =>
    2.   (el => (
    3.     (el = document.querySelector('#' + listID)),
    4.     (el.innerHTML += arr.map(item => `
    5. ${item}
    6. `).join(''))
  •   ))();
  • arrayToHtmlList(['item 1''item 2'], 'myListID');
  • 6. `average`:平均数

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

    7. `averageBy`:数组对象属性平均数

    此代码段将获取数组对象属性的平均值

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

    8.`bifurcate`:拆分断言后的数组

    可以根据每个元素返回的值,使用reduce()push() 将元素添加到第二次参数fn中 。

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

    9. `castArray`:其它类型转数组

    1. const castArray = val => (Array.isArray(val) ? val : [val]);
    2. castArray('foo'); // ['foo']
    3. castArray([1]); // [1]
    4. castArray(1); // [1]

    10. `compact`:去除数组中的无效/无用值

    1. const compact = arr => arr.filter(Boolean);
    2. compact([01false2''3'a''e' * 23NaN's'34]); 
    3. // [ 123'a''s'34 ]

    11. `countOccurrences`:检测数值出现次数

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

    12. `deepFlatten`:递归扁平化数组

    1. const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
    2. deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]

    13. `difference`:寻找差异

    此代码段查找两个数组之间的差异。

    1. const difference = (a, b) => {
    2.   const s = new Set(b);
    3.   return a.filter(x => !s.has(x));
    4. };
    5. difference([123], [124]); // [3]

    14. `differenceBy`:先执行再寻找差异

    在将给定函数应用于两个列表的每个元素之后,此方法返回两个数组之间的差异。

    1. const differenceBy = (a, b, fn) => {
    2.   const s = new Set(b.map(fn));
    3.   return a.filter(x => !s.has(fn(x)));
    4. };
    5. differenceBy([2.11.2], [2.33.4], Math.floor); // [1.2]
    6. differenceBy([{ x2 }, { x1 }], [{ x1 }], v => v.x); // [ { x: 2 } ]

    15. `dropWhile`:删除不符合条件的值

    此代码段从数组顶部开始删除元素,直到传递的函数返回为true

    1. const dropWhile = (arr, func) => {
    2.   while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
    3.   return arr;
    4. };
    5. dropWhile([1234], n => n >= 3); // [3,4]

    16. `flatten`:指定深度扁平化数组

    此代码段第二参数可指定深度。

    1. const flatten = (arr, depth = 1) =>
    2.   arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
    3. flatten([1, [2], 34]); // [1, 2, 3, 4]
    4. flatten([1, [2, [3, [45], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]

    17. `indexOfAll`:返回数组中某值的所有索引

    此代码段可用于获取数组中某个值的所有索引,如果此值中未包含该值,则返回一个空数组。

    1. const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
    2. indexOfAll([123123], 1); // [0,3]
    3. indexOfAll([123], 4); // []

    18. `intersection`:两数组的交集

    1. const intersection = (a, b) => {
    2.   const s = new Set(b);
    3.   return a.filter(x => s.has(x));
    4. };
    5. intersection([123], [432]); // [2, 3]

    19. `intersectionWith`:两数组都符合条件的交集

    此片段可用于在对两个数组的每个元素执行了函数之后,返回两个数组中存在的元素列表。

    1. const intersectionBy = (a, b, fn) => {
    2.   const s = new Set(b.map(fn));
    3.   return a.filter(x => s.has(fn(x)));
    4. };
    5. intersectionBy([2.11.2], [2.33.4], Math.floor); // [2.1]

    20. `intersectionWith`:先比较后返回交集

    1. const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
    2. intersectionWith([11.21.530], [1.9303.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]

    21. `minN`:返回指定长度的升序数组

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

    22. `negate`:根据条件反向筛选

    1. const negate = func => (...args) => !func(...args);
    2. [123456].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]

    23. `randomIntArrayInRange`:生成两数之间指定长度的随机数组

    1. const randomIntArrayInRange = (min, max, n = 1) =>
    2.   Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
    3. randomIntArrayInRange(123510); // [ 34142717302720262114 ]

    24. `sample`:在指定数组中获取随机数

    1. const sample = arr => arr[Math.floor(Math.random() * arr.length)];
    2. sample([37911]); // 9

    25. `sampleSize`:在指定数组中获取指定长度的随机数

    此代码段可用于从数组中获取指定长度的随机数,直至穷尽数组。
    使用Fisher-Yates算法对数组中的元素进行随机选择。

    1. const sampleSize = ([...arr], n = 1) => {
    2.   let m = arr.length;
    3.   while (m) {
    4.     const i = Math.floor(Math.random() * m--);
    5.     [arr[m], arr[i]] = [arr[i], arr[m]];
    6.   }
    7.   return arr.slice(0, n);
    8. };
    9. sampleSize([123], 2); // [3,1]
    10. sampleSize([123], 4); // [2,3,1]

    26. `shuffle`:“洗牌” 数组

    此代码段使用Fisher-Yates算法随机排序数组的元素。

    1. const shuffle = ([...arr]) => {
    2.   let m = arr.length;
    3.   while (m) {
    4.     const i = Math.floor(Math.random() * m--);
    5.     [arr[m], arr[i]] = [arr[i], arr[m]];
    6.   }
    7.   return arr;
    8. };
    9. const foo = [123];
    10. shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]

    27. `nest`:根据`parent_id`生成树结构(阿里一面真题)

    根据每项的parent_id,生成具体树形结构的对象。

    1. const nest = (items, id = null, link = 'parent_id') =>
    2.   items
    3.     .filter(item => item[link] === id)
    4.     .map(item => ({ ...item, childrennest(items, item.id) }));

    用法:

    1. const comments = [
    2.   { id1, parent_id: null },
    3.   { id2, parent_id: 1 },
    4.   { id3, parent_id: 1 },
    5.   { id4, parent_id: 2 },
    6.   { id5, parent_id: 4 }
    7. ];
    8. const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }]


    强烈建议去理解这个的实现,因为这是我亲身遇到的阿里一面真题:

    2. 第二部分:函数

    1.`attempt`:捕获函数运行异常

    该代码段执行一个函数,返回结果或捕获的错误对象。

    1. onst attempt = (fn, ...args) => {
    2.   try {
    3.     return fn(...args);
    4.   } catch (e) {
    5.     return e instanceof Error ? e : new Error(e);
    6.   }
    7. };
    8. var elements = attempt(function(selector) {
    9.   return document.querySelectorAll(selector);
    10. }, '>_>');
    11. if (elements instanceof Error) elements = []; // elements = []

    2. `defer`:推迟执行

    此代码段延迟了函数的执行,直到清除了当前调用堆栈。

    1. const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
    2. defer(console.log'a'), console.log('b'); // logs 'b' then 'a'

    3. `runPromisesInSeries`:运行多个`Promises`

    1. const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
    2. const delay = d => new Promise(r => setTimeout(r, d));
    3. runPromisesInSeries([() => delay(1000), () => delay(2000)]);
    4. //依次执行每个Promises ,总共需要3秒钟才能完成

    4. `timeTaken`:计算函数执行时间

    1. const timeTaken = callback => {
    2.   console.time('timeTaken');
    3.   const r = callback();
    4.   console.timeEnd('timeTaken');
    5.   return r;
    6. };
    7. timeTaken(() => Math.pow(210)); // 1024, (logged): timeTaken: 0.02099609375ms

    5. `createEventHub`:简单的发布/订阅模式

    创建一个发布/订阅(发布-订阅)事件集线,有emitonoff方法。

    1. 使用Object.create(null)创建一个空的hub对象。

    2. emit,根据event参数解析处理程序数组,然后.forEach()通过传入数据作为参数来运行每个处理程序。

    3. on,为事件创建一个数组(若不存在则为空数组),然后.push()将处理程序添加到该数组。

    4. off,用.findIndex()在事件数组中查找处理程序的索引,并使用.splice()删除。

    1. const createEventHub = () => ({
    2.   hubObject.create(null),
    3.   emit(event, data) {
    4.     (this.hub[event] || []).forEach(handler => handler(data));
    5.   },
    6.   on(event, handler) {
    7.     if (!this.hub[event]) this.hub[event] = [];
    8.     this.hub[event].push(handler);
    9.   },
    10.   off(event, handler) {
    11.     const i = (this.hub[event] || []).findIndex(h => h === handler);
    12.     if (i > -1this.hub[event].splice(i, 1);
    13.     if (this.hub[event].length === 0delete this.hub[event];
    14.   }
    15. });

    用法:

    1. const handler = data => console.log(data);
    2. const hub = createEventHub();
    3. let increment = 0;
    4. // 订阅,监听不同事件
    5. hub.on('message', handler);
    6. hub.on('message'() => console.log('Message event fired'));
    7. hub.on('increment'() => increment++);
    8. // 发布:发出事件以调用所有订阅给它们的处理程序,并将数据作为参数传递给它们
    9. hub.emit('message''hello world'); // 打印 'hello world' 和 'Message event fired'
    10. hub.emit('message', { hello'world' }); // 打印 对象 和 'Message event fired'
    11. hub.emit('increment'); // increment = 1
    12. // 停止订阅
    13. hub.off('message', handler);

    6.`memoize`:缓存函数

    通过实例化一个Map对象来创建一个空的缓存。

    通过检查输入值的函数输出是否已缓存,返回存储一个参数的函数,该参数将被提供给已记忆的函数;如果没有,则存储并返回它。

    1. const memoize = fn => {
    2.   const cache = new Map();
    3.   const cached = function(val) {
    4.     return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(thisval)) && cache.get(val);
    5.   };
    6.   cached.cache = cache;
    7.   return cached;
    8. };

    Ps: 这个版本可能不是很清晰,还有Vue源码版的:

    1. /**
    2.  * Create a cached version of a pure function.
    3.  */
    4. export function cached<FFunction> (fn: F): F {
    5.   const cache = Object.create(null)
    6.   return (function cachedFn (str: string{
    7.     const hit = cache[str]
    8.     return hit || (cache[str] = fn(str))
    9.   }: any)
    10. }

    7. `once`:只调用一次的函数

    1. const once = fn => {
    2.   let called = false
    3.   return function () {
    4.     if (!called) {
    5.       called = true
    6.       fn.apply(thisarguments)
    7.     }
    8.   }
    9. };

    8.`flattenObject`:以键的路径扁平化对象

    使用递归。

    1. 利用Object.keys(obj)联合Array.prototype.reduce(),以每片叶子节点转换为扁平的路径节点。

    2. 如果键的值是一个对象,则函数使用调用适当的自身prefix以创建路径Object.assign()

    3. 否则,它将适当的前缀键值对添加到累加器对象。

    4. prefix除非您希望每个键都有一个前缀,否则应始终省略第二个参数。

    1. const flattenObject = (obj, prefix = '') =>
    2.   Object.keys(obj).reduce((acc, k) => {
    3.     const pre = prefix.length ? prefix + '.' : '';
    4.     if (typeof obj[k] === 'object'Object.assign(acc, flattenObject(obj[k], pre + k));
    5.     else acc[pre + k] = obj[k];
    6.     return acc;
    7.   }, {});
    8. flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c'1, d: 1 }

    9. `unflattenObject`:以键的路径展开对象

    与上面的相反,展开对象。

    1. const unflattenObject = obj =>
    2.   Object.keys(obj).reduce((acc, k) => {
    3.     if (k.indexOf('.') !== -1) {
    4.       const keys = k.split('.');
    5.       Object.assign(
    6.         acc,
    7.         JSON.parse(
    8.           '{' +
    9.             keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
    10.             obj[k] +
    11.             '}'.repeat(keys.length)
    12.         )
    13.       );
    14.     } else acc[k] = obj[k];
    15.     return acc;
    16.   }, {});
    17. unflattenObject({ 'a.b.c'1d1 }); // { a: { b: { c: 1 } }, d: 1 }

    这个的用途,在做Tree组件或复杂表单时取值非常舒服。

    3. 第三部分:字符串

    1.`byteSize`:返回字符串的字节长度

    1. const byteSize = str => new Blob([str]).size;
    2. byteSize('😀'); // 4
    3. byteSize('Hello World'); // 11

    2. `capitalize`:首字母大写

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

    3. `capitalizeEveryWord`:每个单词首字母大写

    1. const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
    2. capitalizeEveryWord('hello world!'); // 'Hello World!'

    4. `decapitalize`:首字母小写

    1. const decapitalize = ([first, ...rest]) =>
    2.   first.toLowerCase() + rest.join('')
    3. decapitalize('FooBar'); // 'fooBar'
    4. decapitalize('FooBar'); // 'fooBar'

    5. `luhnCheck`:银行卡号码校验(`luhn`算法)

    Luhn算法的实现,用于验证各种标识号,例如信用卡号,IMEI号,国家提供商标识号等。

    String.prototype.split('')结合使用,以获取数字数组。获得最后一个数字。实施luhn算法。如果被整除,则返回,否则返回。

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

    用例:

    1. luhnCheck('4485275742308327'); // true
    2. luhnCheck(6011329933655299); //  false
    3. luhnCheck(123456789); // false

    补充:银行卡号码的校验规则

    关于luhn算法,可以参考以下文章:

    银行卡号码校验算法(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()和正则表达式匹配换行符并创建一个数组。

    1. const splitLines = str => str.split(/\r?\n/);
    2. splitLines('This\nis a\nmultiline\nstring.\n'); // ['This''is a''multiline''string.' , '']

    7. `stripHTMLTags`:删除字符串中的`HTMl`标签

    从字符串中删除HTML / XML标签。

    使用正则表达式从字符串中删除HTML / XML 标记。

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

      lorem ipsum

      '
      ); // 'lorem ipsum'

    4. 第四部分:对象

    1. `dayOfYear`:当前日期天数

    1. const dayOfYear = date =>
    2.   Math.floor((date - new Date(date.getFullYear(), 00)) / 1000 / 60 / 60 / 24);
    3. dayOfYear(new Date()); // 285

    2. `forOwn`:迭代属性并执行回调

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

    3. `Get Time From Date`:返回当前24小时制时间的字符串

    1. const getColonTimeFromDate = date => date.toTimeString().slice(08);
    2. getColonTimeFromDate(new Date()); // "08:38:00"

    4. `Get Days Between Dates`:返回日期间的天数

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

    5. `is`:检查值是否为特定类型。

    1. const is = (type, val) => ![, null].includes(val) && val.constructor === type;
    2. is(Array, [1]); // true
    3. is(ArrayBuffernew ArrayBuffer()); // true
    4. is(Mapnew Map()); // true
    5. is(RegExp/./g); // true
    6. is(Setnew Set()); // true
    7. is(WeakMapnew WeakMap()); // true
    8. is(WeakSetnew WeakSet()); // true
    9. is(String''); // true
    10. is(Stringnew String('')); // true
    11. is(Number1); // true
    12. is(Numbernew Number(1)); // true
    13. is(Booleantrue); // true
    14. is(Booleannew Boolean(true)); // true

    6. `isAfterDate`:检查是否在某日期后

    1. const isAfterDate = (dateA, dateB) => dateA > dateB;
    2. isAfterDate(new Date(20101021), new Date(20101020)); // true

    7. `isBeforeDate`:检查是否在某日期前

    1. const isBeforeDate = (dateA, dateB) => dateA < dateB;
    2. isBeforeDate(new Date(20101020), new Date(20101021)); // true

    8 `tomorrow`:获取明天的字符串格式时间

    1. const tomorrow = () => {
    2.   let t = new Date();
    3.   t.setDate(t.getDate() + 1);
    4.   return t.toISOString().split('T')[0];
    5. };
    6. tomorrow(); // 2019-10-15 (如果明天是2019-10-15)

    9. `equals`:全等判断

    在两个变量之间进行深度比较以确定它们是否全等。

    此代码段精简的核心在于Array.prototype.every()的使用。

    1. const equals = (a, b) => {
    2.   if (a === b) return true;
    3.   if (a instanceof Date && b instanceof Datereturn a.getTime() === b.getTime();
    4.   if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
    5.   if (a.prototype !== b.prototypereturn false;
    6.   let keys = Object.keys(a);
    7.   if (keys.length !== Object.keys(b).lengthreturn false;
    8.   return keys.every(k => equals(a[k], b[k]));
    9. };

    用法:

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

    5. 第五部分:数字

    1. `randomIntegerInRange`:生成指定范围的随机整数

    1. const randomIntegerInRange = (minmax) => Math.floor(Math.random() * (max - min + 1)) + min;
    2. randomIntegerInRange(05); // 3

    2. `randomNumberInRange`:生成指定范围的随机小数

    1. const randomNumberInRange = (minmax) => Math.random() * (max - min) + min;
    2. randomNumberInRange(210); // 6.0211363285087005

    3. `round`:四舍五入到指定位数

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

    4. `sum`:计算数组或多个数字的总和

    1. const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
    2. sum(1234); // 10
    3. sum(...[1234]); // 10

    5. `toCurrency`:简单的货币单位转换

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

    6. 第六部分:浏览器操作及其它

    1. `bottomVisible`:检查页面底部是否可见

    1. const bottomVisible = () =>
    2.   document.documentElement.clientHeight + window.scrollY >=
    3.   (document.documentElement.scrollHeight || document.documentElement.clientHeight);
    4. bottomVisible(); // true

    2. `Create Directory`:检查创建目录

    此代码段调用fs模块的existsSync()检查目录是否存在,如果不存在,则mkdirSync()创建该目录。

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

    3. `currentURL`:返回当前链接`url`

    1. const currentURL = () => window.location.href;
    2. currentURL(); // 'https://juejin.im'

    4. `distance`:返回两点间的距离

    该代码段通过计算欧几里得距离来返回两点之间的距离。

    1. const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
    2. distance(1123); // 2.23606797749979

    5. `elementContains`:检查是否包含子元素

    此代码段检查父元素是否包含子元素。

    1. const elementContains = (parent, child) => parent !== child && parent.contains(child);
    2. elementContains(document.querySelector('head'), document.querySelector('title')); // true
    3. elementContains(document.querySelector('body'), document.querySelector('body')); // false

    6. `getStyle`:返回指定元素的生效样式

    1. const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
    2. getStyle(document.querySelector('p'), 'font-size'); // '16px'

    7. `getType`:返回值或变量的类型名

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

    8. `hasClass`:校验指定元素的类名

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

    9. `hide`:隐藏所有的指定标签

    1. const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
    2. hide(document.querySelectorAll('img')); // 隐藏所有标签

    10. `httpsRedirect`:`HTTP` 跳转 `HTTPS`

    1. const httpsRedirect = () => {
    2.   if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
    3. };
    4. httpsRedirect(); // 若在`http://www.baidu.com`, 则跳转到`https://www.baidu.com`

    11.`insertAfter`:在指定元素之后插入新元素

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

      after

  • insertAfter(document.getElementById('myId'), '

    after

    '
    ); 
  • 12.`insertBefore`:在指定元素之前插入新元素

    1. const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
    2. insertBefore(document.getElementById('myId'), '

      before

      '
      ); // 

      before

       ...

    13. `isBrowser`:检查是否为浏览器环境

    此代码段可用于确定当前运行时环境是否为浏览器。这有助于避免在服务器(节点)上运行前端模块时出错。

    1. const isBrowser = () => ![typeof windowtypeof document].includes('undefined');
    2. isBrowser(); // true (browser)
    3. isBrowser(); // false (Node)

    14. ` isBrowserTab`:检查当前标签页是否活动

    1. const isBrowserTabFocused = () => !document.hidden;
    2. isBrowserTabFocused(); // true

    15. `nodeListToArray`:转换`nodeList`为数组

    1. const nodeListToArray = nodeList => [...nodeList];
    2. nodeListToArray(document.childNodes); // [ html>, html ]

    16. `Random Hexadecimal Color Code`:随机十六进制颜色

    1. const randomHexColorCode = () => {
    2.   let n = (Math.random() * 0xfffff * 1000000).toString(16);
    3.   return '#' + n.slice(06);
    4. };
    5. randomHexColorCode(); // "#e34155"

    17. `scrollToTop`:平滑滚动至顶部

    该代码段可用于平滑滚动到当前页面的顶部。

    1. const scrollToTop = () => {
    2.   const c = document.documentElement.scrollTop || document.body.scrollTop;
    3.   if (c > 0) {
    4.     window.requestAnimationFrame(scrollToTop);
    5.     window.scrollTo(0, c - c / 8);
    6.   }
    7. };
    8. scrollToTop();

    18. `smoothScroll`:滚动到指定元素区域

    该代码段可将指定元素平滑滚动到浏览器窗口的可见区域。

    1. const smoothScroll = element =>
    2.   document.querySelector(element).scrollIntoView({
    3.     behavior'smooth'
    4.   });
    5. smoothScroll('#fooBar'); 
    6. smoothScroll('.fooBar'); 

    19. `detectDeviceType`:检测移动/PC设备

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

    20. `getScrollPosition`:返回当前的滚动位置

    默认参数为window ,pageXOffset(pageYOffset)为第一选择,没有则用scrollLeft(scrollTop)

    1. const getScrollPosition = (el = window) => ({
    2.   x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
    3.   y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
    4. });
    5. getScrollPosition(); // {x: 0, y: 200}

    21. `size`:获取不同类型变量的长度

    这个的实现非常巧妙,利用Blob类文件对象的特性,获取对象的长度。

    另外,多重三元运算符,是真香。

    1. const size = val =>
    2.   Array.isArray(val)
    3.     ? val.length
    4.     : val && typeof val === 'object'
    5.     ? val.size || val.length || Object.keys(val).length
    6.     : typeof val === 'string'
    7.     ? new Blob([val]).size
    8.     : 0;
    9. size([12345]); // 5
    10. size('size'); // 4
    11. size({ one: 1, two: 2, three: 3 }); // 3

    22. `escapeHTML`:转义`HTML`

    当然是用来防XSS攻击啦。

    1. const escapeHTML = str =>
    2.   str.replace(
    3.     /[&<>'"]/g,
    4.     tag =>
    5.       ({
    6.         '&''&',
    7.         '<''<',
    8.         '>''>',
    9.         "'"''',
    10.         '"''"'
    11.       }[tag] || tag)
    12.   );
    13. escapeHTML('Me & you'); // '<a href="#">Me & you</a>'

  • 相关阅读:
    awk用法:取列表最后一列
    什么是列式存储和行式存储
    Win10电脑需要安装杀毒软件吗?
    优先队列实现
    论文解读(g-U-Nets)《Graph U-Nets》
    让golang程序生成coredump文件并进行调试
    【好奇心驱动力】ESP8266驱动SG90舵机开关灯
    Linux:虚拟机的安转和静态IP的设置过程记录
    webshell流量特征
    植物大战僵尸各种僵尸攻略
  • 原文地址:https://blog.csdn.net/qq_41581588/article/details/125742063