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,一起学习。

相关文章
8086 汇编笔记(五):包含多个段的程序
8086 汇编笔记(五):包含多个段的程序
|
6月前
|
编译器 开发者 C++
8086 汇编笔记(三):第一个程序
8086 汇编笔记(三):第一个程序
|
C++
VS code 编写汇编代码【微机原理】3
VS code 编写汇编代码【微机原理】3
75 0
|
Linux 程序员 C语言
Vs code写C语言代码配置(超详细超基础)
写在前面: 近期不是重新温习一下C语言吗,也给自己升级换代一下编辑器,最初我一直用Dev c++ 写的C语言,因为没想往深的学习C语言,也不会去写什么大的项目,所以这个编辑器也是可以用,但是目前认真学习,发现那个东西真的适合初学者,对于我这种懒人不适合,项目代码管理起来很麻烦,所以一气之下我直接鸟枪换炮,整个大家伙——vs,但是vs真的太大了,而且默认装在C盘,我这破电脑小内存扛不住,所以就研究了一下vs code,下面就本人安装经验给新学者讲解如何安装。
732 0
|
算法 程序员 Go
真实案例(万字长文):Bad Code vs Good Code in Golang
真实案例(万字长文):Bad Code vs Good Code in Golang
|
程序员 开发者
程序员在写code和做管理二者选择时,要切合自身实际来定
写代码还是做管理,这是个老生常谈的命题,就像某明星被离婚一样,隔一段时间就会被提出来供大家讨论。虽然这次话题是这个命题,那就好好的再来聊一次程序员的职业生涯是一直写代码呢还是从写代码转到做管理呢?再借用莎士比亚写的哈姆雷特经典桥段:“生存还是毁灭,这是个问题”,这里我来改编一下:“写代码还是做管理,这是个问题”。
92 0
程序员在写code和做管理二者选择时,要切合自身实际来定
|
前端开发
前端知识学习案例21vs code-跳转或者查看函数定义
前端知识学习案例21vs code-跳转或者查看函数定义
83 0
前端知识学习案例21vs code-跳转或者查看函数定义
|
Python
python中关于IndentationError: expected an indented block 中不易察觉修改原代码错误的解法
python中关于IndentationError: expected an indented block 中不易察觉修改原代码错误的解法
1344 0
python中关于IndentationError: expected an indented block 中不易察觉修改原代码错误的解法
|
Rust 前端开发 rax
Rust为什么放弃Switch结构
今天我们还是继续来聊高并发的话题,我们知道Swich分支是一个非常有用的语法,这是一个可以回溯到上世纪的Pascal、C等经典语言的分支结构,主要的作用就是判断变量的取值并将程序代码送入不同的分支,这种设计在当时的环境下非常的精妙,但是在当前最新的CPU环境下,却会带来很多意想不到的坑。
Rust为什么放弃Switch结构
|
前端开发 rax
[ CALL指令有多少种写法 ] 之读书笔记
原文为360的安全专家很久之前的一篇文章,偶然发现后收获不少。特以笔记的形式记录下来, 便于加深理解。 Intel有公开的指令集格式文档,你需要的是第二卷的上半部分,指令集从A到M。这篇文档的难度超出一般人想象,里面有众多晦涩的标识、与硬件紧密相关的介绍,拿到这后,即使直接翻到目录的CALL 指令一节,也不见得能够弄清楚。
1656 0