干货 | 你应该了解的25个JS技巧 js技术干货分享
yuyutoo 2024-10-18 12:11 3 浏览 0 评论
写代码的时候总有一些东西是会重复出现的,次数多了你就会想找找捷径了。这类问题中有很大一部分解决起来甚至连库都不用装。下面就是我多年来收集的前 25 个捷径和小技巧。
1. 类型检查小工具
JavaScript 不是强类型语言,对此我推荐的最佳解决方案是 TypeScript。但有时你只是想要一个简单的类型检查,这种时候 JavaScript 允许你使用“typeof”关键字。
“typeof”的问题在于,将其用于某些原语和函数时效果很好,但对于数组和对象来说,由于它们都被视为“对象”,因此很难把握它们之间的区别。
const isOfType = (() => {
// create a plain object with no prototype
const type = Object.create(null);
// check for null type
type.null = x => x === null;
// check for undefined type
type.undefined = x => x === undefined;
// check for nil type. Either null or undefined
type.nil = x => type.null(x) || type.undefined(x);
// check for strings and string literal type. e.g: 's', "s", `str`, new String()
type.string = x => !type.nil(x) && (typeof x === 'string' || x instanceof String);
// check for number or number literal type. e.g: 12, 30.5, new Number()
type.number = x => !type.nil(x)
&& (// NaN & Infinity have typeof "number" and this excludes that
(!isNaN(x) && isFinite(x)
&& typeof x === 'number'
) || x instanceof Number);
// check for boolean or boolean literal type. e.g: true, false, new Boolean()
type.boolean = x => !type.nil(x) && (typeof x === 'boolean' || x instanceof Boolean);
// check for array type
type.array = x => !type.nil(x) && Array.isArray(x);
// check for object or object literal type. e.g: {}, new Object(), Object.create(null)
type.object = x => ({}).toString.call(x) === '[object Object]';
// check for provided type instance
type.type = (x, X) => !type.nil(x) && x instanceof X;
// check for set type
type.set = x => type.type(x, Set);
// check for map type
type.map = x => type.type(x, Map);
// check for date type
type.date = x => type.type(x, Date);
return type;
})();
2. 检查是否为空
有时你需要知道某些内容是否为空,并根据结果决定要使用的方法,例如检查长度、大小或是否包含任何子元素。下面这个工具打包了这些功能,你可以用它检查 String、Object、Array、Map 和 Set 的大小。
function isEmpty(x) {
if(Array.isArray(x)
|| typeof x === 'string'
|| x instanceof String
) {
return x.length === 0;
}
if(x instanceof Map || x instanceof Set) {
return x.size === 0;
}
if(({}).toString.call(x) === '[object Object]') {
return Object.keys(x).length === 0;
}
return false;
}
3. 获取列表最后一项
其他语言里这个功能被做成了可以在数组上调用的方法或函数,但在 JavaScript 里面,你得自己做点工作。
function lastItem(list) {
if(Array.isArray(list)) {
return list.slice(-1)[0];
}
if(list instanceof Set) {
return Array.from(list).slice(-1)[0];
}
if(list instanceof Map) {
return Array.from(list.values()).slice(-1)[0];
}
}
4. 带有范围的随机数生成器
有时你需要生成随机数,但希望这些数字在一定范围内,那就可以用这个工具。
function randomNumber(max = 1, min = 0) {
if(min >= max) {
return max;
}
return Math.floor(Math.random() * (max - min) + min);
}
5. 随机 ID 生成器
有时你只是需要一些 ID?除非你要的是更复杂的 ID 生成器(例如 UUID),否则用不着为此安装什么新库,下面这个选项足够了。你可以从当前时间(以毫秒为单位)或特定的整数和增量开始生成,也可以从字母生成 ID。
// create unique id starting from current time in milliseconds
// incrementing it by 1 everytime requested
const uniqueId = (() => {
const id = (function*() {
let mil = new Date().getTime();
while (true)
yield mil += 1;
})();
return () => id.next().value;
})();
// create unique incrementing id starting from provided value or zero
// good for temporary things or things that id resets
const uniqueIncrementingId = ((lastId = 0) => {
const id = (function*() {
let numb = lastId;
while (true)
yield numb += 1;
})()
return (length = 12) => `${id.next().value}`.padStart(length, '0');
})();
// create unique id from letters and numbers
const uniqueAlphaNumericId = (() => {
const heyStack = '0123456789abcdefghijklmnopqrstuvwxyz';
const randomInt = () => Math.floor(Math.random() * Math.floor(heyStack.length))
return (length = 24) => Array.from({length}, () => heyStack[randomInt()]).join('');
})();
6. 创建一个范围内的数字
Python 里我很喜欢的一个功能是 range 函数,而在 JavaScript 里我经常需要自己写这个功能。下面是一个简单的实现,非常适合 for…of 循环以及需要特定范围内数字的情况。
function range(maxOrStart, end = null, step = null) {
if(!end) {
return Array.from({length: maxOrStart}, (_, i) => i)
}
if(end <= maxOrStart) {
return [];
}
if(step !== null) {
return Array.from(
{length: Math.ceil(((end - maxOrStart) / step))},
(_, i) => (i * step) + maxOrStart
);
}
return Array.from(
{length: Math.ceil((end - maxOrStart))},
(_, i) => i + maxOrStart
);
}
7. 格式化 JSON 字符串,stringify 任何内容
我在使用 NodeJs 将对象记录到控制台时经常使用这种方法。JSON.stringify 方法需要第三个参数,该参数必须有多个空格以缩进行。第二个参数可以为 null,但你可以用它来处理 function、Set、Map、Symbol 之类 JSON.stringify 方法无法处理或完全忽略的内容。
const stringify = (() => {
const replacer = (key, val) => {
if(typeof val === 'symbol') {
return val.toString();
}
if(val instanceof Set) {
return Array.from(val);
}
if(val instanceof Map) {
return Array.from(val.entries());
}
if(typeof val === 'function') {
return val.toString();
}
return val;
}
return (obj, spaces = 0) => JSON.stringify(obj, replacer, spaces)
})();
8. 顺序执行 promise
如果你有一堆异步或普通函数都返回 promise,要求你一个接一个地执行,这个工具就会很有用。它会获取函数或 promise 列表,并使用数组 reduce 方法按顺序解析它们。
const asyncSequentializer = (() => {
const toPromise = (x) => {
if(x instanceof Promise) { // if promise just return it
return x;
}
if(typeof x === 'function') {
// if function is not async this will turn its result into a promise
// if it is async this will await for the result
return (async () => await x())();
}
return Promise.resolve(x)
}
return (list) => {
const results = [];
return list
.reduce((lastPromise, currentPromise) => {
return lastPromise.then(res => {
results.push(res); // collect the results
return toPromise(currentPromise);
});
}, toPromise(list.shift()))
// collect the final result and return the array of results as resolved promise
.then(res => Promise.resolve([...results, res]));
}
})();
9. 轮询数据
如果你需要持续检查数据更新,但系统中没有 WebSocket,则可以使用这个工具来执行操作。它非常适合上传文件时,想要持续检查文件是否已完成处理的情况,或者使用第三方 API(例如 dropbox 或 uber)并且想要持续检查过程是否完成或骑手是否到达目的地的情况。
async function poll(fn, validate, interval = 2500) {
const resolver = async (resolve, reject) => {
try { // catch any error thrown by the "fn" function
const result = await fn(); // fn does not need to be asynchronous or return promise
// call validator to see if the data is at the state to stop the polling
const valid = validate(result);
if (valid === true) {
resolve(result);
} else if (valid === false) {
setTimeout(resolver, interval, resolve, reject);
} // if validator returns anything other than "true" or "false" it stops polling
} catch (e) {
reject(e);
}
};
return new Promise(resolver);
}
10. 等待所有 promise 完成
这个算不上是代码解决方案,更多是对 Promise API 的强化。这个 API 在不断进化,以前我还为“allSettled”“race”和“any”做了代码实现,现在直接用 API 的就好了。
11. 交换数组值的位置
ES6 开始,从数组中的不同位置交换值变得容易多了。这个做起来不难,但是了解一下也不错,
12. 条件对象键
我最喜欢这条技巧了,我在使用 React 更新状态时经常用它。你可以将条件包装在括号中来有条件地将一个键插入一个 spread 对象。
13. 使用变量作为对象键
当你有一个字符串变量,并想将其用作对象中的键以设置一个值时可以用它。
14. 检查对象里的键
这是一个很好的技巧,可以帮助你检查对象键。
15. 删除数组重复项
数组中经常有重复的值,你可以使用 Set 数据结构来消除它。它适用于许多数据类型,并且 set 有多种检查相等性的方法,很好用。对于不同实例或对象的情况,你还是可以使用 Set 来跟踪特定事物并过滤出重复的对象。
16. 在 ArrayforEach 中执行“break”和“continue”
我真的很喜欢使用数组“.forEach”方法,但有时我需要提早退出或继续进行下一个循环,而不想用 for...loop。你可以复制“continue”语句行为来提前返回,但如果要复制“break”行为,则需要使用数组“.some”方法。
17. 使用别名和默认值来销毁
Destructuring(销毁)是 JavaScript 最好用的功能之一,而且你可以使用“冒号”设置别名,并使用“等号”设置属性默认值。
18. 可选链和空值合并
深入检查对象属性并处理 null 和 undefined 值时,你可以使用几个非常好用的 JavaScript 功能来解决常见的问题。
19. 用函数扩展类
我经常对别人讲,JavaScript 类只是构造函数和底层的原型,不是像 Java 中那样的真实概念。一个证据是,你可以只使用一个构造函数来扩展一个类。在私有内容里这个很好用,在类里“#”这些看着很奇怪,并且用于 babel 或 WebPack 时,编译出来的代码更少。
20. 扩展构造函数
类的一个问题是你只能扩展一个其他类。使用构造函数,你可以使用多个构造函数来构成一个函数,这样就会灵活多了。你可以使用函数原型的.apply 或.call 方法来实现。你甚至可以只扩展函数的一部分,只要它是一个对象即可。
21. 循环任何内容
有时,你需要循环任何可迭代的内容(Set、Map、Object、Array、String 等)。这个非常简单的 forEach 函数工具就可以做到这一点。如果回调返回 true,它将退出循环。
function forEach(list, callback) {
const entries = Object.entries(list);
let i = 0;
const len = entries.length;
for(;i < len; i++) {
const res = callback(entries[i][1], entries[i][0], list);
if(res === true) break;
}
}
22. 使函数参数为 required
这是一种确保函数调用了完成工作所需内容的绝佳方法。你可以使用默认参数值的特性来调用函数,然后就会抛出一个错误。如果调用该函数时带上了它需要的值,则该值将替换该函数,并且什么也不会发生。使用 undefined 调用也有相同的效果。
function required(argName = 'param') {
throw new Error(`"${argName}" is required`)
}
function iHaveRequiredOptions(arg1 = required('arg1'), arg2 = 10) {
console.log(arg1, arg2)
}
iHaveRequiredOptions(); // throws "arg1" is required
iHaveRequiredOptions(12); // prints 12, 10
iHaveRequiredOptions(12, 24); // prints 12, 24
iHaveRequiredOptions(undefined, 24); // throws "arg1" is required
23. 创建模块或单例
很多时候,你需要在加载时初始化某些内容,设置它需要的各种事物,然后就可以在应用程序中到处使用它,而无需再做什么补充工作。你可以使用 IIFE 函数来做到这一点,这个函数太好用了。这种模块模式用来隔离事物非常好用,它可以只暴露需要交互的内容。
24. 深度克隆对象
开发人员通常会安装一些类似“lodash”的库来执行这一操作,但使用纯 JavaScript 来实现确实也很容易。这是一个简单的递归函数:只要是一个对象,就使用函数的构造器将其重新初始化为一个克隆,然后对所有属性重复该过程。
const deepClone = obj => {
let clone = obj;
if (obj && typeof obj === "object") {
clone = new obj.constructor();
Object.getOwnPropertyNames(obj).forEach(
prop => (clone[prop] = deepClone(obj[prop]))
);
}
return clone;
};
25. 深度冻结对象
如果你喜欢不变性,那么这个工具你一定要常备。
const deepClone = obj => {
let clone = obj;
if (obj && typeof obj === "object") {
clone = new obj.constructor();
Object.getOwnPropertyNames(obj).forEach(
prop => (clone[prop] = deepClone(obj[prop]))
);
}
return clone;
};
原文链接:
25 Javascript Code Solutions Utility Tricks You Need to Know About
https://beforesemicolon.medium.com/25-javascript-code-solutions-utility-tricks-you-need-to-know-about-3023f7ed993e
延伸阅读:
2021 年,这8种编程语言最流行-InfoQ
关注我并转发此篇文章,即可获得学习资料~若想了解更多,也可移步InfoQ官网,获取InfoQ最新资讯~
相关推荐
- 高一高二第一次月考认真作答(高二第一次月考的重要性)
-
正在进行高一、高二第一次月考,同学们正在认真完成化学试卷,研究考纲,探究考点,夯实基础,迎战高考!
- 山清水秀,盛世今朝(山清水秀出处)
-
万千星河,神州妖娆!山清水秀,盛世今朝!龙腾虎跃,锦绣前程!千里婵娟,祝福永远!
- 我校二模成绩已新鲜出炉(二模考试成绩)
-
充电加油备战高考,积极努力再拼一搏...
- Argon Design向瑞萨电子有限公司提供Argon Streams VP9许可证
-
英国剑桥--(美国商业资讯)--领先的先进视频验证解决方案提供商ArgonDesignLtd已与日本半导体公司瑞萨电子有限公司(RenesasElectronicsCorporation)签署...
- 高考倒计时75天(高考倒计时75天励志语)
-
今天是2022年3月24日星期四,距离2022年高考还有75天时间对于十八岁的高三学子来说,有些事情的确会影响你们的一生,但是没有一件事能决定你们的一生!努力的意义,就是:以后的日子里,放眼望去,全...
- 期中考试正在进行(期中考试在即)
-
转眼即瞬,期中考试已到,紧张忙碌的两个月学习,检验的时刻到了。让我们拿出信心和勇气,来挑战自我。面对考验,我们该做的就是沉着,冷静。让知识来一次次洗礼我们的灵魂,让失败和成功迎接一次次的成长。你们可以...
- 不要浪费了你NAS上的HDMI接口!详解华硕NAS上HDMI接口的妙用
-
不要浪费了你NAS上的HDMI接口!详解华硕NAS上HDMI接口的妙用之前我在本站分享我使用的华硕(ASUS)AS6704T...
- Java通过Kafka Streams库来实现数据流处理
-
#暑期创作大赛#...
- From abandoned mines to limpid streams waters: how banks profit from EOD
-
ByZENGYanglinInthecurrentpursuitofthe“dualcarbon”target(carbonpeakingandcarbonneutra...
- SPSS与Streams的集成实现实时预测
-
SPSSModeler是一个数据挖掘工作台,提供了一个可了解数据并生成预测模型的最先进的环境。Streams提供了一个可伸缩的高性能环境,对不断变化的数据进行实时分析,这些数据中包括传统结构的数据...
- Kafka Streams, 我还会再使用它吗?
-
DeeptiMittal4分钟阅读...
- 大数据Hadoop之——Kafka Streams原理介绍与简单应用示例
-
一、KafkaStreams概述官网文档:https://kafka.apache.org/32/documentation/streams/...
- Android上的TCP今天开始向用户推出,并将在下个月向所有用户提供
-
据extends网3月15日报道,Firefox今天宣布,其保护用户免受跟踪器攻击的全面cookie保护(TCP)功能现已在Android上可用。该功能默认启动模式,这样,跟踪器将无法收集有关用户的浏...
- Linux curl命令(linux curl命令安装)
-
Linuxcurl命令是一个利用URL规则在命令行下工作的文件传输工具。它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称curl为下载工具。作为一款强力工具,curl支持包括HTTP、H...
- go语言http服务入门详解(go语言http服务器)
-
当你在浏览器中输入URL时,实际上是在发送一个对Web页面的请求。该请求被发送到服务器。服务器的工作是获取适当的页面并将其作为响应发送回浏览器。在Web的早期,服务器通常读取服务器硬盘上HTML文件的...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- 高一高二第一次月考认真作答(高二第一次月考的重要性)
- 山清水秀,盛世今朝(山清水秀出处)
- 我校二模成绩已新鲜出炉(二模考试成绩)
- Argon Design向瑞萨电子有限公司提供Argon Streams VP9许可证
- 高考倒计时75天(高考倒计时75天励志语)
- 期中考试正在进行(期中考试在即)
- 不要浪费了你NAS上的HDMI接口!详解华硕NAS上HDMI接口的妙用
- Java通过Kafka Streams库来实现数据流处理
- From abandoned mines to limpid streams waters: how banks profit from EOD
- SPSS与Streams的集成实现实时预测
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)