这些一行 JS 实现功能的代码,让你看起来像一个前端专家

JavaScript 可以做很多神奇的事情!

从复杂的框架到处理 API,有太多的东西需要学习。

但是,它也能让你只用一行代码就能做一些了不起的事情。

下面这些 JavaScript 单行代码,会让你看起来像个专家!

1. 通过Math.random随机获取值

随机布尔值 (true/false)
使用 Math.random 将在 0 和 1 之间创建一个随机数,之后我们检查它是否高于或低于 0.5。这意味着得到真或假的几率是 50%/50%。

const randomBoolean = () => Math.random() >= 0.5;
console.log(randomBoolean());
// Result: a 50/50 change on returning true of false

// 生成随机字符串
Math.random().toString(36).slice(2) // fgvwj5eiat

随机指定范围数值

const range = (max, min) => Math.round(Math.random() * (max - min) + min);
range(1, 5); // 随机生成 1~5之间的数据(包括1,5)
数组随机排序

数组排序使用 Array.sort ,此方法返回值为: 小于0 等于0 大于0 ,小于0则数值大和数值小的交换,等于0则不交换,大于0则数值小的和数值大的交换,知道这个规则,我们可以实现随机返回正数,负数,或0来实现乱序排序(俗称洗牌)。

const arr = [134, 4, 3, 7, 6, 788, 34, 76, 2];
console.log(arr.sort(() => Math.random() - 0.5)); // [134, 4, 34, 6, 7, 3, 788, 2, 76]
console.log(arr.sort(() => Math.random() - 0.5)); // [788, 76, 3, 2, 6, 34, 4, 7, 134]
console.log(arr.sort(() => Math.random() - 0.5)); // [2, 7, 4, 788, 76, 3, 134, 6, 34]

2. 检查日期是否为工作日

使用这个方法,你就可以检查函数参数是工作日还是周末。

const isWeekday = (date) => date.getDay() % 6 !== 0;
console.log(isWeekday(new Date(2021, 0, 11)));
// Result: true (Monday)
console.log(isWeekday(new Date(2021, 0, 10)));
// Result: false (Sunday)

3. 反转字符串

有几种不同的方法来反转一个字符串。以下代码是最简单的方式之一。

const reverse = str => str.split('').reverse().join('');
reverse('hello world');     
// Result: 'dlrow olleh'

4.检查当前 Tab 页是否在前台

我们可以通过使用 document.hidden 属性来检查当前标签页是否在前台中。

const isBrowserTabInView = () => document.hidden;
isBrowserTabInView();
// Result: returns true or false depending on if tab is in view / focus

5. 检查数字是否为偶数

最简单的方式是通过使用模数运算符(%)来解决。如果你对它不太熟悉,这里是 Stack Overflow上的一个很好的图解。

const isEven = num => num % 2 === 0;
console.log(isEven(2));
// Result: true
console.log(isEven(3));
// Result: false

6.从日期中获取时间

通过使用 toTimeString() 方法,在正确的位置对字符串进行切片,我们可以从提供的日期中获取时间或者当前时间。

const timeFromDate = date => date.toTimeString().slice(0, 8);
console.log(timeFromDate(new Date(2021, 0, 10, 17, 30, 0))); 
// Result: "17:30:00"
console.log(timeFromDate(new Date()));
// Result: will log the current time

7. 保留小数点(非四舍五入)

使用 Math.pow() 方法,我们可以将一个数字截断到某个小数点。

const toFixed = (n, fixed) => ~~(Math.pow(10, fixed) * n) / Math.pow(10, fixed);
// Examples
toFixed(25.198726354, 1);       // 25.1
toFixed(25.198726354, 2);       // 25.19
toFixed(25.198726354, 3);       // 25.198
toFixed(25.198726354, 4);       // 25.1987
toFixed(25.198726354, 5);       // 25.19872
toFixed(25.198726354, 6);       // 25.198726

8. 检查元素当前是否为聚焦状态

我们可以使用 document.activeElement 属性检查一个元素当前是否处于聚焦状态。

const elementIsInFocus = (el) => (el === document.activeElement);
elementIsInFocus(anyElement)
// Result: will return true if in focus, false if not in focus

9. 检查浏览器是否支持触摸事件

const touchSupported = () => {
  ('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch);
}
console.log(touchSupported());
// Result: will return true if touch events are supported, false if not

10. 检查当前用户是否为苹果设备

我们可以使用 navigator.platform 来检查当前用户是否为苹果设备。

const isAppleDevice = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
console.log(isAppleDevice);
// Result: will return true if user is on an Apple device

11. 滚动到页面顶部

window.scrollTo() 方法会取一个 x 和 y 坐标来进行滚动。如果我们将这些坐标设置为零,就可以滚动到页面的顶部。
注意:IE 不支持 scrollTo() 方法。

const goToTop = () => window.scrollTo(0, 0);
goToTop();
// Result: will scroll the browser to the top of the page

12. 获取所有参数平均值

我们可以使用 reduce 方法来获得函数参数的平均值

const average = (...args) => args.reduce((a, b) => a + b) / args.length;
average(1, 2, 3, 4);
// Result: 2.5

13. 转换华氏度/摄氏度。

处理温度有时会让人感到困惑。这 2 个功能将帮助你将华氏温度转换为摄氏温度,反之亦然。

const celsiusToFahrenheit = (celsius) => celsius * 9/5 + 32;
const fahrenheitToCelsius = (fahrenheit) => (fahrenheit - 32) * 5/9;
// Examples
celsiusToFahrenheit(15);    // 59
celsiusToFahrenheit(0);     // 32
celsiusToFahrenheit(-20);   // -4
fahrenheitToCelsius(59);    // 15
fahrenheitToCelsius(32);    // 0

14. 快速取整

const n1 = 3.1245;
console.log(~~n1); // 3
console.log(~~5.9545); // 5
console.log(~~134.166545); // 134
console.log(~~-45.34); // -45
console.log(~~-1.845); // -1
console.log(~~-0.845); // 0

15. 月份日期前面补零

// 假设日期是 2021 年 3 月 6 日 早上 8 点 7 分 9秒
const date = new Date(2021, 2, 6, 8, 7, 9);
// 希望展示格式如果是各位则前面补零
console.log(0${date.getMonth() + 1}.slice(-2)); // 03
console.log(0${date.getHours()}.slice(-2)) // 08
上面看懂了吗?就是 前面补0然后 slice(-2),从后往前截取两位
011.slice(-2) // 11
01.slice(-2) // 01
09.slice(-2) // 09

16. 多状态切换

例如排序状态的切换, asc -> desc -> default -> asc 
状态的切换是个闭环,状态由前一个变为下一个,如果到了最后一个状态又变回第一个状态。
我们定义一个数组,用来表示要切换的排序
function nextOrder(order) {
    const orders = ['asc', 'desc', 'default'];
    return orders[(orders.indexOf(order) + 1) % orders.length];
}
如上我们实现一个排序的切换过程
console.log(nextOrder('asc')); // desc
console.log(nextOrder('desc')); // default
console.log(nextOrder('default')); // asc
console.log(nextOrder('asc')); // desc

17. 测试一个字符由两个字节还是由四个字节组成的最简单方法

function is32Bit(c) {
  return c.codePointAt(0) > 0xFFFF;
}

is32Bit("𠮷") // true (注意这个“𠮷”不是吉祥的“吉”)
/*
  这里科普一下:
    JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。
    对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF的字符),JavaScript 会认为它们是两个字符。

  如上所说
  '𠮷'.length // 2, 因为该 Unicode 码点大于 0xFFFF
  '吉'.length // 1
*/
is32Bit("a") // false


// 判断用户输入字符串长度
function codePointLength(text) {
  var result = text.match(/[\s\S]/gu);
  return result ? result.length : 0;
}
var s = '𠮷𠮷';

s.length // 4
codePointLength(s) // 2

18. 浮点数对比时精度丢失解决

ES6 在Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。
Number.EPSILON实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。
引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围。我们知道浮点数计算是不精确的。

0.1 + 0.2 === 0.3 // 结果为false
// 因为 0.1 + 0.2 结果为 0.30000000000000004

// 故而出现以下结果
0.1 + 0.2 - 0.3  // 5.551115123125783e-17

// 判断浮点数运算后的结果是否相等
function isEqual(left, right) {
  return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}

isEqual(0.1 + 0.2, 0.3) // true
isEqual(1.1 + 1.3, 2.4) // true

19. 浮点加法运算数精度丢失问题

// 获取小数点的长度
function getDotLength(n) {
  const s = String(n).split('.');
  return s.length > 1 ? s[1].length : 0;
}

// 浮点数计算器 加法
function floatCalculatorAdd(...args) {
  // 获取所有数字小数位的长度
  const floatLengths = args.map((cur) => {
    cur = Number(cur) || 0; // 转成 number,类型,无法转number类型的默认为0
    return getDotLength(cur);
  });
  // 获取最长的小数点位数
  const maxFloatLen = Math.max(...floatLengths);
  // 放大bei shubeishu
  const scale = Math.pow(10, maxFloatLen);
  const res = args
    .map(n => (Number(n) || 0) * scale)
    .reduce((acc, cur) => acc + cur, 0);
  return res / scale;
}

floatCalculatorAdd(0.1, 0.2) // 0.3
floatCalculatorAdd(1, 3.12, '2.456', 'AF', 0, -123.2) // -116.624

20. 组合函数

// 组合函数
const composeFn = (...funcs) => val => funcs.reduce((a, b) => b(a), val);

/*
  应用场景:
    例如对一个字符串实现去除前后空格,首字母大写,并在结尾加上句号
    这个时候我们代码实现方式可能如下
*/

// 去除前后空格函数
const trim = str => str.replace(/(^\s+)|(\s+$)/g, '');

// 首字母转大写函数
const firstLetterUpper = str => str.slice(0, 1).toUpperCase() + str.slice(1);

// 字符串最后添加。符号
const addSuffix = str => str + '。';

var str = " hi, I am Andy ";
// 实现需求
addSuffix(firstLetterUpper(trim(str))); // Hi, I am Andy。


// 利用组合函数,将多个操作组合成一个函数,方便使用。
const formatStr = composeFn(trim, firstLetterUpper, addSuffix);

formatStr(str); // Hi, I am Andy。

21. 查询参数转为对象

Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }

22. 数组的平铺 flattern 函数

function flattern(array) {
  if (!Array.isArray(array)) {
    return array;
  }
  return [].concat(...array.map(flattern));
}
flattern([1, 2, [3, 4, [5, 6, [7, 8]]]]); // [1, 2, 3, 4, 5, 6. 7, 8]

23. 金额格式化展示

const options = {
  style: 'currency',
  currency: 'CNY',
};
(91249.139).toLocaleString('zh-CN', options); // ¥91,249.14  (小数点后面会进行四舍五入)
(99999.9999).toLocaleString(options);  // 100,000

24. 将一串数字转换成从右往左每三位数用逗号分隔

function formatNum(num) {
    // (\+|-)? 表示 正负号; (\d+) 表示整数部分; (\.\d+)? 表示小数部分
    if (!/^(\+|-)?(\d+)(\.\d+)?$/.test(num)) {            
      // 不满足规则说明传递来的数据不是一个正常数字的格式
      alert("wrong!"); return num; 
  }

  // 上面已经执行了test,所以这里的a、b、c已经是能够获得值的了,分别是正负号、整数部分、小数部分。
  var a = RegExp.$1, b = RegExp.$2, c = RegExp.$3;

  // 用来匹配出整数部分 首次出现连续四个数字加一个逗号 或者 结尾连续四个数字 的形式;
  var re =/(\d)(\d{3})(,|$)/;

  // 从左往右匹配 当遇到第一个逗号就停止,或者没有逗号一直到结尾停止。这样拿到逗号(结尾)前四个数字
  while (re.test(b)) {
    // 将匹配成功的四个数字,替换成一个数字加逗号加三个数字的形式
    // $1 表示正则表达式中的第一个子表达式,也就是 (\d) ,它表示匹配到的四个数字中的第一个数字
    // $2 也就是 (\d{3}) , 表示匹配到的 后面三个数字
    // $3 也就是 (,|$) , 表示匹配到的四个数字后面的 逗号或者空(结尾就是空)
    // replace方法是不影响原字符串的,它返回一个替换好的新字符串,所以这里要将替换好的覆盖原来的
    b = b.replace(re, "$1,$2$3");

    // 由于re不是全局的正则表达式( 没有加参数g ),所以每次循环替换首次匹配成功的一处
    // 也就是 每次循环 拿到 整数部分第一个逗号往前数的 四个数字
    // 然后 将拿到的四个数字中 在第一个数字与后三个数字之间加上逗号
    // 直到整数部分从左往右 匹配不到 连续四个数字加逗号 的形式,循环结束
  }

  // 拼接原来的正负号、已分隔好的整数部分、原来的小数部分
  return a + "" + b + "" + c;
}

formatNum('1123456')    // 1,123,456
formatNum('-123456789.1234')    // -123,456,789.1234

25. 转义HTML特殊字符

如果你了解 XSS,解决方案之一就是转义 HTML 字符串

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

escape('<div class="medium">Hi Medium.</div>') // "&lt;div class=&quot;medium&quot;&gt;Hi Medium.&lt;/div&gt;"

26. 将字符串中每个单词的第一个字符大写

此方法用于将字符串中每个单词的第一个字符大写。

const uppercaseWords = str => str.replace(/^(.)|\s+(.)/g, c => c.toUpperCase())

uppercaseWords('hello world') // Hello World

27. 将字符串转换为驼峰命名法

const toCamelCase = str => str.trim().replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : '')


toCamelCase('background-color'); // backgroundColor
toCamelCase('-webkit-scrollbar-thumb'); // WebkitScrollbarThumb
toCamelCase('_hello_world'); // HelloWorld
toCamelCase('hello_world'); // helloWorld

28. 数组对象根据某个字段去重

/**
 * 数组根据某个字段去重
 * @param {*} arr 对象数组
 * @param {*} field 对象字段
 * @returns 去重后的数组
 */
function uniqueArrayByField(arr, field) {
    const map = new Map() // 利用 map 特性,可以做到高性能
    return arr.filter(item => !map.has(item[field]) && map.set(item[field], 1))
}

// 例如根据 arr 对象的 stuId 字段去重
uniqueArrayByField(arr, 'stuId')

29. 使用位操作

// 取模
if (value % 2) { // 奇数
} else { // 偶数
}

// 位操作
if (value & 1) { // 奇数
} else { // 偶数
}
 
// 二进制左位移
const a = 1 << 0 // 1
const b = 1 << 1 // 2
const c = 1 << 2 // 4
const d = 1 << 3 // 8

a | b // 3
b | c // 6
c | d // 12
d | d // 8
a | b | c | d // 15

30. 响应式图片

通过 picture 实现

<picture>
    <source srcset="banner_w1000.jpg" media="(min-width: 801px)">
    <source srcset="banner_w800.jpg" media="(max-width: 800px)">
    <img src="banner.jpg" alt="">
</picture>

通过 @media 实现

@media (min-width: 769px) {
    .bg {
        background-image: url(bg1080.jpg);
    }
}
@media (max-width: 768px) {
    .bg {
        background-image: url(bg768.jpg);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容