30 second of code 15个有意思的代码段

简介: 30-seconds 是一个学习系列,基本都是通过简短的代码实现某些功能, 包含30-seconds-of-code满足所有开发需求的简短JavaScript代码片段30-seconds-of-css满足所有开发需求的简短CSS代码片段30-seconds-of-react满足所有开发需求的简短React代码片段等等,还有很多系列, 我们今天的主题是 30-seconds-of-code , 即简短的代码段。挑选了我觉得比较有意思或者有意义的15个代码,我们一起开始简短代码之旅吧!

1.JPG


前言



30-seconds 是一个学习系列,基本都是通过简短的代码实现某些功能, 包含



等等,还有很多系列, 我们今天的主题是 30-seconds-of-code , 即简短的代码段。

挑选了我觉得比较有意思或者有意义的15个代码,我们一起开始简短代码之旅吧!


精选



URLJoin


地址拼接。 除此之外,URLSearchParamsURL都可以很好的处理QueryString, 更多详情参见 私藏的这些高级工具函数,你拥有几个?


const URLJoin = (...args) =>
  args
    .join('/')
    .replace(/[\/]+/g, '/')
    .replace(/^(.+):\//, '$1://')
    .replace(/^file:/, 'file:/')
    .replace(/\/(\?|&|#[^!])/g, '$1')
    .replace(/\?/g, '&')
    .replace('&', '?');
复制代码


示例

URLJoin('http://www.google.com', 'a', '/b/cd', '?foo=123', '?bar=foo');
// 'http://www.google.com/a/b/cd?foo=123&bar=foo'
复制代码


uncurry


减少嵌套函数调用次数,改变函数的传参方式。 这是反柯里化吗?

这个函数非常灵活,很有意思。


const uncurry = (fn, n = 1) => (...args) => {
  const next = acc => args => args.reduce((x, y) => x(y), acc);
  if (n > args.length) throw new RangeError('Arguments too few!');
  return next(fn)(args.slice(0, n));
};
复制代码
const add = x => y => z => x + y + z;
const uncurriedAdd1 = uncurry(add, 1);
uncurriedAdd1(1)(2)(3)  // 6
const uncurriedAdd1 = uncurry(add, 2);
uncurriedAdd1(1,2)(3)  // 6
const uncurriedAdd3 = uncurry(add, 3);
uncurriedAdd3(1, 2, 3); // 6
复制代码


onScrollStop


监听滚动停止事件,当停止滚动的时候,执行回调函数。


需要在停止滚动后,执行某些操作,还是很有用的。


const onScrollStop = callback => {
  let isScrolling;
  window.addEventListener(
    'scroll',
    e => {
      clearTimeout(isScrolling);
      isScrolling = setTimeout(() => {
        callback();
      }, 150);
    },
    false
  );
};
复制代码
onScrollStop(() => {
  console.log('The user has stopped scrolling');
});
复制代码


byteSize


返回字符串字节数。


都知道,中文和英文所占的字节数是不一样的,有占两个的,三个的,四个的,一个的。


英文一般一个字节,中文一般三个。


const byteSize = str => new Blob([str]).size;
复制代码
byteSize('a') // 1
byteSize('س') // 2
byteSize('中') // 3
byteSize('😀'); // 4
byteSize('Hello World'); // 11
复制代码


这还涉及 Unicode编码的知识,为了验证更多字符,你可以查阅 Unicode对应表

runPromisesInSeries


顺序执行promise, 实际上应该生成Promise的函数。


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)]);
// Executes each promise sequentially, taking a total of 3 seconds to complete
复制代码


这个版本,不能传参,我在 私藏的这些高级工具函数,你拥有几个?, 实现了一个带参数版本。


function runPromises(promiseCreators, initData) {
    return promiseCreators
        .reduce((promise, next) => promise
                .then((data) => next(data))
            , Promise.resolve(initData));
}
复制代码
var promise1 = function (data = 0) {
    return new Promise(resolve => {
        resolve(data + 1000);
    });
}
var promise2 = function (data) {
    return new Promise(resolve => {
        resolve(data -500);
    });
}
runPromises([promise1, promise2], 1).then(res=>console.log(res));  // 501
复制代码


stringifyCircularJSON


将包含循环引用的 JSON 对象序列化为 JSON 格式。


其思路是使用WeakSet 保存数据进行对比。


const stringifyCircularJSON = obj => {
  const seen = new WeakSet();
  return JSON.stringify(obj, (k, v) => {
    if (v !== null && typeof v === 'object') {
      if (seen.has(v)) return;
      seen.add(v);
    }
    return v;
  });
};
复制代码
const obj = { n: 42 };
obj.obj = obj;
stringifyCircularJSON(obj); // '{"n": 42}'
复制代码


UUIDGeneratorBrowser


UUID生成器,除此之外URL.createObjectURL也可以生成UUID。这两种算是比较主流的方式。


const UUIDGeneratorBrowser = () =>
  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
    (
      c ^
      (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
    ).toString(16)
  );
复制代码
UUIDGeneratorBrowser(); // '7982fcfe-5721-4632-bede-6000885be57d'
复制代码
function genUUID() {
    const url = URL.createObjectURL(new Blob([]));
    // const uuid = url.split("/").pop();
    const uuid = url.substring(url.lastIndexOf('/')+ 1);
    URL.revokeObjectURL(url);
    return uuid;
}
genUUID() // cd205467-0120-47b0-9444-894736d873c7
复制代码


addDaysToDate


时间添加天数,返回的是字符串。


const addDaysToDate = (date, n) => {
  const d = new Date(date);
  d.setDate(d.getDate() + n);
  return d.toISOString().split('T')[0];
};
复制代码
addDaysToDate('2020-10-15', 10); // '2020-10-25'
addDaysToDate('2020-10-15', -10); // '2020-10-05'
复制代码


compose


从右到左的复合函数。 没记错的话和 redux的compose 极其类似。

毕竟嘛,思路是一样的。


onst compose = (...fns) =>
  fns.reduce((f, g) => (...args) => f(g(...args)));
复制代码
const add5 = x => x + 5;
const multiply = (x, y) => x * y;
const multiplyAndAdd5 = compose(
  add5,
  multiply
);
multiplyAndAdd5(5, 2); // 15
复制代码


deepGet


获取对象的多级属性,属性参数是数组。


const deepGet = (obj, keys) =>
  keys.reduce(
    (xs, x) => (xs && xs[x] !== null && xs[x] !== undefined ? xs[x] : null),
    obj
  );
let index = 2;
const data = {
  foo: {
    foz: [1, 2, 3],
    bar: {
      baz: ['a', 'b', 'c']
    }
  }
};
deepGet(data, ['foo', 'foz', index]); // get 3
deepGet(data, ['foo', 'bar', 'baz', 8, 'foz']); // null
复制代码


当然 lodash 也提供了 .get, 当然实现的复杂度也高很对,其属性参数用的是字符串。


objectToQueryString


把对象转为 queryString,就这个queryString的转换,就有好几个牛气冲天的库。

下载量过 千万的 query-string 和 500万的 qs, 主要解决两个问题,其中一个就是 toQueryString。


const objectToQueryString = queryParameters => {
  return queryParameters
    ? Object.entries(queryParameters).reduce(
        (queryString, [key, val], index) => {
          const symbol = queryString.length === 0 ? '?' : '&';
          queryString +=
            typeof val === 'string' ? `${symbol}${key}=${val}` : '';
          return queryString;
        },
        ''
      )
    : '';
};
复制代码
objectToQueryString({ page: '1', size: '2kg', key: undefined });
// '?page=1&size=2kg'
复制代码


parseCookie


把cookie转为键值对。


作为一个操作前端,操作cookie是日常操作,我相信肯定有不少同志引入了第三方库,其实只需代几码就可以的。


const parseCookie = str =>
  str
    .split(';')
    .map(v => v.split('='))
    .reduce((acc, v) => {
      acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
      return acc;
    }, {});
复制代码
parseCookie(document.cookie) 
// {_octo: "GH1.1.2059864283.1626332708", tz: "Asia/Shanghai"}
parseCookie('foo=bar; equation=E%3Dmc%5E2');
// { foo: 'bar', equation: 'E=mc^2' }
复制代码


unfold


使用迭代器函数和初始种子值构建数组。

在造假数据或者随机数据的时候,比较有用。


const unfold = (fn, seed) => {
  let result = [],
    val = [null, seed];
  while ((val = fn(val[1]))) result.push(val[0]);
  return result;
};
复制代码
var f = n => (n > 50 ? false : [-n, n + 10]);
unfold(f, 10); // [-10, -20, -30, -40, -50]
复制代码


triggerEvent


触发给定元素上的特定事件,可以选择传递自定义数据。


这个在IE11以及一些低版本是有问题的,低版本使用的是 document.createEvent


const triggerEvent = (el, eventType, detail) =>
  el.dispatchEvent(new CustomEvent(eventType, { detail }));
复制代码
triggerEvent(document.getElementById('myId'), 'click');
triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });
复制代码


repeatGenerator


创建生成器,无限重复给定值。 有点意思,实用场景嘛,也许测试吧。

当然,中途你可以更新值。 这里想告诉大家的是 genetator有入参的概念。


const repeatGenerator = function* (val) {
  let v = val;
  while (true) {
    let newV = yield v;
    if (newV !== undefined) v = newV;
  }
};
复制代码
const repeater = repeatGenerator(5);
repeater.next(); // { value: 5, done: false }
repeater.next(); // { value: 5, done: false }
repeater.next(4); // { value: 4, done: false }
repeater.next(); // { value: 4, done: false }
复制代码


写在最后



如果你觉得不错,你的一赞一评就是我前行的最大动力。

技术交流群请到 这里来。 或者添加我的微信 dirge-cloud,一起学习。

相关文章
|
7月前
|
程序员 编译器 C++
【实用编程技巧】不想改bug?初学者必须学会使用的报错函数assert!(断言函数详解)
【实用编程技巧】不想改bug?初学者必须学会使用的报错函数assert!(断言函数详解)
68 2
|
2月前
|
Java
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
文章详细解释了Java关键字`super`的用途,包括访问父类的成员变量、调用父类的构造方法和方法,并提供了相应的代码实例。
180 5
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
|
25天前
|
C语言
【C语言】全局搜索变量却找不到定义?原来是因为宏!
使用条件编译和 `extern` 来管理全局变量的定义和声明是一种有效的技术,但应谨慎使用。在可能的情况下,应该优先考虑使用局部变量、函数参数和返回值、静态变量或者更高级的封装技术(如结构体和类)来减少全局变量的使用。
31 5
|
2月前
|
Java
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
本文介绍了Java中this和super关键字的用法,包括在构造方法中使用this来区分参数和成员变量、使用super调用父类构造方法和方法,以及它们在同一个方法中同时使用的场景。
156 0
Java关键字 —— super 与 this 详细解释!一看就懂 有代码实例运行!
|
3月前
|
API Windows
MASM32编程完善SysInfo遇到奇怪故障,真切感受全局变量和局部变量之别……
MASM32编程完善SysInfo遇到奇怪故障,真切感受全局变量和局部变量之别……
8086 汇编笔记(五):包含多个段的程序
8086 汇编笔记(五):包含多个段的程序
|
7月前
|
编译器 开发者 C++
8086 汇编笔记(三):第一个程序
8086 汇编笔记(三):第一个程序
|
7月前
|
Unix Linux C语言
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
【C/C++ 跳转函数】setjmp 和 longjmp 函数的巧妙运用: C 语言错误处理实践
119 0
|
数据可视化 安全 Java
拥有Low-code源代码对程序有哪些作用?
拥有Low-code源代码对程序有哪些作用?
|
前端开发
前端知识学习案例21vs code-跳转或者查看函数定义
前端知识学习案例21vs code-跳转或者查看函数定义
90 0
前端知识学习案例21vs code-跳转或者查看函数定义