原文在 https://areknawo.com/5-interesting-and-not-necessarily-useful-javascript-tricks/
做者是 Areknawojavascript
前一段时间,我建立了一个标题为“7个可爱的Web开发技巧”的帖子。在这里,我描述了一些有趣的技巧,您可使用3种主要的Web技术之一来实现这些技巧-HTML,CSS和JavaScript。并且,我必须认可-大家彷佛都喜欢它!所以,续集来了!java
此次,为了更加一致,我决定只专一于JavaScript。它多是三者中最有趣,用途最普遍的,所以有不少事情要讨论。咱们将介绍5种JavaScript技巧,这些技巧在上一篇文章中没有提到。但愿您会发现它们颇有趣!node
在进入列表以前,请快速注意一下。我看到了对上一篇文章的一些回复,并想清除一些内容。我知道并非该列表或上一个列表中的全部条目可能都是真正有用的或推荐的作法,但这不是个人目标。用“技巧”一词个人意思就是-有趣的或仅出于此目的而值得了解的“技巧”。有用只是一种奖励。若是它打算100%有用,那么我将其称为“提示”。我但愿你明白。如今,让咱们转到列表!git
从不太“极端”的技巧开始,咱们获得了switch声明。它的大多数用例都归结为字符串或数字值匹配。可是,您知道您也能够将其与一些更复杂的布尔值一块儿使用吗?看一看。web
const useSwitch = value => { let message = ""; switch (true) { case value < 0: message = "lesser than 0"; break; case value === 0: message = "0"; break; case value % 1 !== 0: message = "a float"; break; case value > 0 && value <= 9: message = "higher than 0 and is 1 digit long"; break; case value >= 10 && value <= 99: message = "2 digits long"; break; case value >= 100: message = "big"; break; } console.log(`The value is ${message}`); }; useSwitch(24); // The value is 2 digits long.
而不是为switch语句提供实际变量,咱们只是传递true。这样,咱们实质上使它成为一个大if-else选择。是否应使用它仅取决于您的我的喜爱或所遵循的代码准则。若是您发现它比if-else链条更具可读性,那就去买它。两种解决方案的性能大体相同。浏览器
接下来,咱们有一些自己并非真正的技巧。对函数进行字符串化是您很长时间以来最了解的功能。相反,我想让您知道这种功能的一些有趣用例。缓存
const func = () => { console.log("This is a function"); } const stringifiedFunc = `${func}`; /* `() => { console.log("This is a function"); }` */
首先快速看一下语法方面。您应该知道,当您将任何JS类型的值转换为字符串时,.toString()都会调用一个特殊方法。您可使用此事实来实现此方法的本身的版本,并以不一样的方式处理将JS值转换为字符串的状况。能够单独考虑这是一个技巧。;)不管如何,我想说的是,您能够将值(包括函数)转换为带有ES6模板文字的字符串(如示例中所示),方法是将它们与空字符串文字("")串联,或者仅经过调用该.toString()方法直接。less
如今,让咱们回到函数。我想指出,您不能依赖结果字符串来包含函数编写时的全部代码。例如,它仅来自ES2019(当前为ECMAScript标准的最新版本),其.toString()目的是在结果字符串中包含函数体内的全部注释和空格。您能够我以前的一篇文章中阅读有关ES2019功能的更多信息。不管如何,考虑到全部这些,对函数进行字符串化怎么可能甚至有用?ecmascript
不要搜索太多,我想引用一个我最近的副项目中使用的巧妙技巧。想象一下,能够经过调用一个函数来建立一种节点。该函数将另外一个函数用做参数,而后运行该参数以配置新节点。对于包含相同语句的函数,结果节点相同。函数
可悲的是,建立新节点是一个缓慢的过程(尤为是考虑大量节点时),而且您至少要最小化要建立的节点数。为此,您能够例如建立一个“缓存”对象,在该对象中经过其字符串化的config函数存储全部已建立的节点,以防止进行任何重复调用-有趣吗?
固然,即便是很小的空格或注释,基于字符串的基于函数的ID也会被认为是不一样的。您能够经过一些附加的字符串处理来解决它,可是这会忽略咱们试图实现的全部性能改进。
可是,只要配置功能容许,您就不能容忍对象键。您能够经过简单地对字符串化函数进行哈希处理来轻松解决此问题-它不会在性能上花费不少。
// ... const hash = value => { let hashed = 0; for (let i = 0; i < value.length; i += 1) { hashed = (hashed << 5) - hashed + value.charCodeAt(i); hashed |= 0; } return `${hashed}`; }; const hashedFunc = hash(stringifiedFunc); // "-1627423388"
我知道我刚刚描述的内容彷佛过于具体,没法应用于更通常的用例。固然能够,可是我只是想给您一个现实的例子,说明这种技巧给您带来的可能性。
可调用对象,具备属性的函数或任何您想调用的对象都是一个很是简单的想法,能够很好地演示JavaScript的多功能性。
const func = () => { // ... }; func.prop = "value"; console.log(func.prop); // "value"
上面的代码段对您来讲彷佛没有什么特别。您能够在几乎任何JS对象保存本身的属性,除非它与使用说明,不然.freeze(),.seal()或.preventExtensions()方法。上面的函数如今既能够用做常规函数,也能够用做包含某种数据的对象。
上面的代码片断看起来并不完美。将属性分配给给定的函数可能会随着时间的推移而感到重复和混乱。让咱们尝试改变它!
const func = Object.assign(() => { // ... }, { prop: "value" }); console.log(func.prop); // "value"
如今,咱们正在使用该Object.assign()方法来使咱们的代码看起来更好。固然,此方法仅在与ES6兼容的环境中(或与Transpiler一块儿使用)可用,可是,因为咱们还在此处使用箭头功能,所以我认为这是理所固然的。
假设咱们有一个包含许多字段和方法的类。您能够想象本身在这种状况下,不是吗?若是在给定的时刻仅须要全部类属性和方法的一小部分怎么办?也许您可使用ES6 解构分配来使代码看起来更好?可悲的是,这并不容易-看一下。
class Example { method() { console.log(this); } } const instance = new Example(); const { method } = instance; method(); // undefined
如您所见,在提取方法以后,将value this更改成undefined。这是预期的行为-的价值this是运行时绑定和方式和地点,你的函数被调用在肯定我在讨论这个。我之前的帖子。
有一个办法解决,可是- .bind()。
class Example { constructor() { this.method = this.method.bind(this); } method() { console.log(this); } } const instance = new Example(); const { method } = instance; method(); // Example {}
如今,咱们的代码能够按预期工做,尽管它须要添加类构造函数,并所以增长了几行代码。咱们能够缩短期吗?
class Example { method = () => { console.log(this); } } // ...
看来咱们已经作到了!在您的类中具备按词法绑定的方法的简便快捷方法。上面的语法可最新的常绿浏览器中使用,并在必要时能够进行编译,请尽情使用!
此列表上的最后一个条目也与类相关。您可能据说过从构造函数返回自定义值的可能性。这不是很受欢迎或推荐的作法,可是它可使您得到一些有趣的结果。还记得我以前提出的缓存节点的先前示例吗?让咱们以此为基础!
// ... const cache = {}; class Node { constructor(config) { const id = hash(`${config}`); if (cache[id]) { return cache[id]; } else { cache[id] = this; config(); } } } const node = new Node(() => {}); const nodeReference = new Node(() => {}); const secondNode = new Node(() => { console.log("Hello"); }); console.log(node === nodeReference, node === secondNode); // true, false
咱们的节点如今具备类的形式,而且像之前同样,可使用字符串化和哈希配置函数对其进行缓存。看到全部片断融合在一块儿真是太好了!
因此,仅此而已。我知道这不是您见过的最长的一个,可是,嘿,至少我设法使您感兴趣,对吗?不管如何,请在评论部分让我知道您不知道上述哪些技巧?另外,您还能够在这种文章中分享您的意见,若是您想查看更多文章,请与咱们分享。;)
最后,我很快宣布了一个消息-我正在创建本身的Reddit社区!它被称为r / Areknawo,我但愿它成为这个博客(像您这样的博客)的读者的地方,以讨论各类帖子,博客相关的内容以及其余与Web开发,设计或技术相关的内容。若是您想表达您的支持,只需去那里,成为会员,而后赶忙离开。;)
所以,若是您喜欢此博客,请考虑在Twitter,Facebook或Reddit上关注我,以获取最新内容。若是您喜欢时事通信,则在帖子下方可使用一种表格来注册。与往常同样,感谢您阅读本文,并祝您愉快!
机翻搬运没有公众号须要你关注