14个 JavaScript 中鲜为人知的技巧
英文 | http://developer.51cto.com/art/201912/607686.htm
1、void 操作符
2、构造函数后面的括号是可选的
3、IIFE 函数的括号可以省略
4、with 声明
with (object)
statement
// for multiple statements add a block
with (object) {
statement
statement
...
}
with 把传入的对象的所有属性添加到当前作用域链中:
趣闻
with听起来非常酷,对吧?它甚至比对象解构更好。
好吧,不是这样的。
通常不建议使用with语句,因为它已被弃用。在严格模式下完全禁止这样做。事实证明,使用块会增加该语言的性能和安全性问题!
译者注:
不建议使用with,因为with语句将对象的成员添加到当前作用域,从而无法说出块内的变量实际指的是什么。由于难以调试和读取这些类型的功能,因此许多人认为这是一种不好的做法。
5、Function 构造函数
函数声明不是定义新函数的唯一方法;您可以使用Function()构造函数以及new运算符动态地定义函数。
最后一个构造函数参数是函数的字符串化代码以及之前的其他参数为函数参数。
趣闻
Function 构造函数是 JavaScript 中所有构造函数的母亲。甚至Object的构造函数都是Function构造函数。Function自己的构造函数也是Function本身。因此,调用object.constructor.constructor ...足够的次数最终将返回JavaScript中任何对象上的Function构造函数。
6、函数属性
众所周知,函数是JavaScript中的「一等公民」。因此,没有人阻止我们向函数添加自定义属性。这在JS中是完全正确的事情。但是,它很少使用。
那么我们什么时候想要这样做呢?
嗯,有一些很好的用例。例如:
可配置函数
假设我们有一个叫做greet的函数。我们希望我们的函数根据不同的语言环境打印不同的问候消息。此语言环境也应该是可配置的。我们可以在某个地方维护全局语言环境变量,也可以使用如下所示的函数属性来实现函数:
带有静态变量的函数
另一个类似的例子。假设您要实现一个数字生成器——该数字生成器生成一系列有序数字。通常,您将使用带有静态的counter变量的类或IIFE来跟踪上一个值。这样,我们可以限制访问counter,还可以避免因额外的变量污染全局空间。
但是,如果我们想灵活地读取甚至修改计数器而又不污染全局空间怎么办?
是的,我们仍然可以创建一个类,它带有counter变量和一些其他读取counter的方法;或者我们偷个懒,只在函数上使用属性。
7、参数属性
我敢肯定你们大多数人都知道函数内的arguments对象。它是一个数组,类似于对象,可以在所有函数中使用。它具有在调用时传递给函数的参数列表。但是它还具有其他一些有趣的特性,
arguments.callee:引用当前调用的函数
arguments.callee.caller:引用已调用当前函数的函数
注意:尽管ES5禁止在严格模式下使用 callee 和 caller,但在许多已编译的库中仍然很常见。因此,值得学习。
8、标记模板字符串
除非您与世隔绝,否则您肯定听说过模版字符串。模版字符串是ES6提供的许多不错的功能之一。但是,您知道标记模版字符串吗?
带有标记的模板字符串可以通过向模板字符串添加自定义标记,来更好地控制将模板字符串解析为字符串的过程。Tag只是一个解析器函数,它获取由字符串模板解释的所有字符串和值的数组,并返回最终字符串。
在下面的示例中,我们的自定义标签highlight解释模板字符串的值,并且还将解释后的值使用元素包装在结果字符串中以突出显示。
在许多库都可以发现一些有趣的用例是利用此功能来实现的。
以下是一些很酷的例子,
react styled-components
es2015-i18n-tag 用于翻译和国际化
chalk 用于彩色的 log
9、Getters & Setters
在大多数情况下,JavaScript对象很简单。假设我们有一个user对象,并尝试使用user.age访问其年龄属性,如果定义了年龄属性,我们将获得年龄属性的值;否则,将获得未定义属性。简单。
但是,可以不必这么简单。JavaScript对象具有Getter和Setter的概念。可以直接编写自定义Getter函数以返回所需的任何内容,而不是直接返回对象的值。设置值也一样。
这使我们在获取或设置字段时拥有虚拟字段,字段验证,副作用等强大的能力。
Getters和Setters在 ES5 中不是新增功能。他们一直在那里。ES5 只是在现有功能中添加了方便的语法。要了解有关 Getters&Setters的更多信息,请参阅这篇不错的文章)
Colors 是一个流行的node.js库,它是利用Getters的一个很好的例子。
该库扩展了String类,并在其上添加了一堆Getter方法。这使我们能够通过简单地访问其属性,将任何字符串转换为其彩色版本,以便于打印。
10、逗号操作符
JavaScript 具有逗号运算符。它允许我们在一行中编写多个用逗号分隔的表达式,并返回最后一个表达式的结果。
// syntax
let result = expression1, expression2,... expressionN
在上面的代码中,将对所有表达式进行求值,并将对expressionN 返回的值赋值给result变量。
您可能已经在for循环中使用了逗号运算符:
for (var a = 0, b = 10; a <= 10; a++, b--)
有时它可以用来帮助我们在同一行中写多个语句:
function getNextValue() {
return counter++, console.log(counter), counter
}
或者写短的 lamda 函数:
const getSquare = x => (console.log (x), x * x)
11、加号操作符
你是否曾经遇到过需要将字符串快速转换为数字的场景?
只需在字符串前面加上+运算符即可。
加号运算符还适用于负,八进制,十六进制,指数值。而且,它甚至可以将Date或Moment.js对象转换为时间戳!
12、!! Bang Bang 操作符
好的,从技术上讲,它不是独立的 JavaScript 运算符。只是把 JavaScript 否定运算符使用了两次。
但是Bang Bang(!!)听起来很酷!Bang Bang或Double Bang是将所有表达式转换为布尔值的巧妙技巧。
如果表达式是 truthy 的值,则返回 true;否则返回 false。
13、~ 按位操作符
面对现实吧——没人在乎按位运算符。我们什么时候才能使用它!
好吧,按位非(~)运算符每天都有用例。
事实证明,当与数字一起使用时,按位非运算符才有效。比如:〜N =>-(N + 1)。仅当N == -1时,此表达式的计算结果才为“ 0”。
我们可以通过将〜放在indexOf(...)函数前面来检查某一项是否存在于一个字符串或者数组中:
注意:ES6和ES7分别在String和Array中添加了一个新的.includes()方法。无疑,这是一种比~运算符更简洁的方法来检查数组或字符串中是否存在项。
14、带标签的声明
JavaScript 具有label语句的概念。它允许我们在 JavaScript 中命名循环和块。然后,我们可以在以后使用break或continue时使用这些标签来引用代码。
带标签的语句在嵌套循环中特别方便。但是我们也可以使用它们将代码简单地组织成块或创建可退出的块。