本文为翻译
原文标题:JavaScript's Forgotten Keyword (with)
原文作者:Randall
原文地址:dev.to/mistval/jav…
JavaScript 开发 可真是一份令人兴奋的工作。几乎每天你都能发现一些神秘又另类的东西。有时是惊喜,有时是惊吓。
在本文中,我会介绍 “with”关键字。它是 JavaScript 语言中的一个阴暗的角落,即便是那些资深开发者很少能注意到。
用法
我们可以使用 with 关键字帮助我们打印一条消息到 console:
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 查找某个未使用命名空间的变量时,会通过作用域链来查找,作用域链是跟执行代码的 context 或者包含这个变量的函数有关。“with” 语句将某个对象添加到作用域链的顶部,如果在 statement 中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出 ReferenceError 异常。
简单来说就是:当你在代码中写一个标识符的时候(就像前文中代码段里的 log 或者 join ),JavaScript 会查找 作用域链 上的对象,如果其中有对象的属性名 和 你在代码中写的这个标识符 一致,JavaScript 就会使用该对象的属性值。
with 关键字允许你注入任何对象到 作用域链 顶部。这里我列了一个例子,应该能更清晰的解释这一点:
with ({ myProperty: 'Hello world!' }) {
console.log(myProperty); // Logs "Hello world!"
}
别用它
看起来 “with” 棒极了,对吧?嗯,也许不是。
在大多数情况下,使用临时变量就能达到同样的效果,而且自从 结构赋值 出现后,这么做越来越方便了。
此外,MDN 列出了一些陷阱:
在严格模式下被禁用
你不能在严格模式下使用 with 。考虑到 ES module 和 class 会自动启用严格模式,这种限制几乎消灭了任何 with 在现代开发中使用的可能性。
意外的变量遮蔽(Variable shadowing)
思考下面的代码,我们将两个数求平均,然后将结果四舍五入:
function getAverage(min, max) {
with (Math) {
return round((min + max) / 2);
}
}
getAverage(1, 5);
最终返回是 NaN 。为什么?因为 Math.min() 和 Math.max() 遮蔽 了函数接收的参数,所以我们最终是在将两个函数相加,当然就是 NaN 了。
基本上,你如果用了 with , 你就不得不小心翼翼的选择标识符的命名了。你必须检查你往 with 里传了什么东西,确认其中的属性不会导致 高层作用域的 变量遮蔽 。
使用 with 还可能引发安全漏洞。如果 传入 with 的对象 被 攻击者添加一些属性,那么就可能会遮蔽你的标识符,并会通过各种你意想不到的方式影响你程序的行为。
例如,从一个未经过验证的 JSON HTTP 请求体 中解析得到 JS对象 后,直接传给 with,这么做是极其危险的行为。
性能
把东西添加到 作用域链,你会降低代码的运行速度,因为你增加了 在解析标识符到实际值时 所需要搜索的对象数量。
被排斥
如果你用 with 关键字,所有人都会认为你疯了,然后在吃午饭的时候远离你。也有可能,他们会用滑稽的表情看着你。
无论如何,使用这种没人知道的神奇语言特性只会让你的代码更难维护,而且其实它也没给你带来多少好处。
结论
with 关键字为 JavaScript 增添了一些有趣的能力,但是到头来 弊大于利,我个人不推荐使用。
当然,不要只听我的一家之言。似乎 MDN 也对 with 恨之入骨,在严格模式中禁用它是有原因的。
我写 JavaScript 超过 5 年了,令我惊讶的是,直到今天我还在学习语言的关键字,这些关键字甚至都不是最近才出现的。到底还有什么知识点在潜藏着呢?
with 源于什么?谁设计的?为什么?是想实现类似于 C++ 命名空间的东西吗?是 通灵板 告诉他们怎么做的吗?
不管是什么情况,看起来被长期遗忘的 with 要被永远的扔进历史的垃圾箱了。
就像黑魔法一样,有趣 又 混乱!