这些一行 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
数组随机排序

数组排序使用 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]

推荐阅读更多精彩内容