JavaScript 中被遗忘的关键字(附)
成为一名 JavaScript 开发者可能是一项令人兴奋的工作。几乎每天都会遇到一些神秘莫测、超凡脱俗的事情。有时,这是一种神奇的体验,有时,则令人毛骨悚然。
在本文中,我们将研究“with”关键字。它是语言中的一个隐患,即使是经验丰富的开发人员也常常没有意识到。
用法
让我们使用with关键字来帮助我们将消息记录到控制台:
with (console) {
log('I dont need the "console." part anymore!');
}
让我们用它来将数组连接成字符串:
with (console) {
with (['a', 'b', 'c']) {
log(join('')); // writes "abc" to the console.
}
}
是的,我的朋友们,不管你信不信,这就是 JavaScript。
“with” 的作用是什么
以下是来自 MDN 的解释:
JavaScript 通过搜索与包含该非限定名称的脚本或函数的执行上下文关联的作用域链来查找非限定名称。with 语句在执行其语句主体时,会将给定的对象添加到此作用域链的头部。如果语句主体中使用的非限定名称与作用域链中的属性匹配,则该名称将绑定到该属性以及包含该属性的对象。否则,将抛出 ReferenceError。
希望可以更简单地重新表述一下:当您在代码中编写标识符时(如log
上面join
的代码片段中所示),JavaScript 会查看一系列对象,如果其中一个对象具有与您在代码中编写的标识符同名的属性,JavaScript 将使用该属性的值。
关键字with
允许你将任意对象注入到该链的前端。以下是另一个可能更清晰的例子:
with ({ myProperty: 'Hello world!' }) {
console.log(myProperty); // Logs "Hello world!"
}
不要使用它
很棒吧?是啊,也可能不是。
在大多数情况下,只需使用临时变量即可达到相同的效果,自从解构出现以来,这比以往任何时候都更容易。
此外,MDN还列出了一些陷阱:
严格模式下禁止
无法with
在严格模式下使用。考虑到ES 模块with
和类会自动处于严格模式,这种限制甚至扼杀了在许多现代用例中使用的可能性。
意外的跟踪
考虑以下代码来计算两个数字的平均值并将结果四舍五入为整数:
function getAverage(min, max) {
with (Math) {
return round((min + max) / 2);
}
}
getAverage(1, 5);
这将返回NaN
。为什么?因为Math.min()
和Math.max()
遮蔽了函数的参数,所以我们最终计算了两个函数的和,这当然是 NaN。
基本上,如果你使用with
,你就必须更加谨慎地选择标识符。你必须仔细检查你传入的内容,with
以确保它不包含可能在更高作用域中无意中影响其他内容的属性。
此行为也可能带来安全漏洞。如果攻击者能够向你传递给 的对象添加属性with
,那么他们就可以隐藏你的标识符,并以意想不到的方式修改你的代码行为。
举个例子,传递一个从未经验证的 JSON HTTP 请求主体解析出来的对象with
是极其危险的。
表现
通过向作用域链添加某些内容,几乎会减慢每一行代码的速度,因为您增加了需要搜索以将标识符解析为值的对象的数量。
放逐
如果你使用这个with
关键词,每个人都会认为你疯了,在餐厅里躲着你。或者他们可能只是用奇怪的眼神看着你。
无论哪种方式,使用别人不知道的神奇语言功能都会使您的代码更难维护,在这种情况下不会给您带来太多好处。
结论
该with
关键字为该语言增加了一些有趣的功能,但最终它带来了太多的缺点和太少的优点,因此我不推荐使用它。
当然,别光听我的。MDN似乎非常讨厌它,而且出于某种原因,它在严格模式下被禁止。
我写 JavaScript 已经五年多了,但令我惊讶的是,直到今天我还在学习那些早已过时的语言关键字。这里面可能还隐藏着什么呢?
它从何而来with
?谁设想的?为什么?他们想要类似 C++ 命名空间的东西吗?还是通灵板让他们这么做的?
无论如何,这句早已被遗忘的with
声明似乎将永远被扔进历史的垃圾箱。
尽管像许多黑暗艺术一样,玩起来很有趣!
文章来源:https://dev.to/mistval/javascript-s-forgotten-keyword-with-48id