9 个用于算法的简洁 JavaScript 代码段
英文 | https://medium.com/geekculture/9-neat-javascript-one-liners-for-algorithms-and-more-8dd3b0a0fb6d
翻译 | 杨小爱
const wrap = (arr, steps) => arr[steps % arr.length];
wrap(['a','b','c'], 0) // a
wrap(['a','b','c'], 1) // b
wrap(['a','b','c'], 2) // c
wrap(['a','b','c'], 3) // a
// etc ...
您可以根据步骤以不同的方式实现这一点,但要理解的关键是modulo。这是一个方便的小运算符。在查看此类“溢出”类型问题时请记住它。
02、用它的名字记录一个变量
这是调试时的一个很好的技巧。多亏了对象速记符号,我们可以默认用名称注销变量。
const someVar = 1;
console.log({ someVar });
// logs out { someVar: 1 }
如果您放入一堆日志(并且在调试时您完全会这样做),则可能很难跟踪哪个是哪个,所有异步、获取和循环都在四处奔波。不必花时间输入像 console.log('some var', someVar) 这样的多个参数,而是在一些大括号中折腾并称它为一天。
03、对象中的可选属性
如果您不希望属性指向 undefined 或 null ,您可以使用一些 if 语句来选择性地添加属性:
//...
const obj = {
a: 'whatever',
};
if (b) {
obj.c = 'ok';
}
return obj;
//...
然而,它太冗长了,我一直讨厌它。这可能很清楚,但很笨拙。好吧,由于对象传播,这已成为过去:
return {
a: 'Whatever',
...(b && { c: 'ok'}),
};
我们可以使用扩展和&&逻辑短路来动态检查是否通过扩展来添加属性。当您只想返回一个对象而不想创建临时变量时,这非常有用。
04、在 JavaScript 中睡眠
有几次我不得不处理一个很糟糕的 API,它很慢,而且在它完成时没有钩子可以说。因此,我们只需要等待一秒钟以确保它已加载。我们还想使用 promises 而不是 setTimeout 回调,因此使用 sleep 函数是理想的。我们可以简单地等待一秒钟,然后继续前进。不需要回调!
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
这也是如何承诺 setInterval 。
05、交换变量值
在现代 JS 之前,如果你想切换两个变量的值,你必须引入第三个“临时”值。现在我们有了数组解构和赋值,我们可以在一行中完成:
a = 10;
b = 5;
[a,b] = [b,a];
// a is 5, b is 10
06、四舍五入到最接近的 10、100、1000……
如果您需要将数字粗略计算到不同级别,这在算法中很有用。基本上,您要做的是先除以将小数向上移动。“无用”数字现在是小数,您可以将它们四舍五入。要将数字恢复到所需大小,请将其相乘。被忽略的数字现在变成零。这是处理金钱或类似对数的尺度的巧妙技巧,在某个点之后,小数字可以四舍五入。
const rounder = (val, place) => Math.round(val / place) * place;
rounder(1549, 100); // 1500
rounder(15590, 1000); // 16000
07、使用 Set 删除重复项
我刚刚写了关于 Sets 的文章,显然这是它们唯一的用途。如果您有一个数组并且想要删除重复项,则可以使用 Set 来完成。
const val = [...new Set([1,2,1,3,1,4])];
// [ 1, 2, 3, 4 ]
不要忘记将新 Set 散布回常规数组中。注意:处理大量列表时要小心,因为这可能不是性能最高的解决方案。
08、计数字符实例
如果您有一个数组(或来自字符串的数组)并且想知道字符出现了多少次,那么使用 reduce 有一种非常巧妙的方法可以做到这一点。
const charTotals = (arr) => arr.reduce((totals, char) => ({
...totals, [char]: (totals[char] || 0) + 1,
}), {});
charTotals('Hi there!'.split(''));
// { H: 1, i: 1, ' ': 1, t: 1, h: 1, e: 2, r: 1, '!': 1 }
这个可能不是那么有用,但是我想确保您知道两种技术:动态对象属性和对象的隐式返回。这两件事都是至关重要的知识,如果您不了解 reduce,请阅读本文。
09、身份证制造商/柜台
我想我需要为反应组件动态创建非数据库临时 ID,并将经典计数器压缩到一行中。每次调用该函数时,计数器都会增加,并且没有其他函数可以改变其内部状态。它使用闭包、立即调用函数表达式和默认值来保持紧凑。
const counter = ((num = 1) => () => num++)();
counter() // 1
counter() // 2
counter() // 3
还有一个额外提示,即在函数参数中使用默认值以避免需要换行。如果你真的想让起始数字变得动态,你可以停止让它成为 IIFE:
const startCounter = (num = 1) => () => num++);
const counter100 = startCounter(100)
counter100() // 100
counter100() // 101
counter100() // 102
总结
你得到了代码的简洁,也有可能你失去代码的可读性。
最终如何取舍,这取决于您和您的团队喜欢什么,在编程的世界里,没有完美,只有谁更加符合需求,符合项目进度。因此,请不要刻意追求简洁,保持代码的可读性依然重要。
最后,感谢您的阅读,祝您编码愉快。
学习更多技能
请点击下方公众号