阅读 108

with 是什么?

前言

with 语句 扩展一个语句的作用域链。

JavaScript 查找某个未使用命名空间的变量时,会通过作用域链来查找,作用域链是跟执行代码的 context 或者包含这个变量的函数有关。with语句将某个对象添加到作用域链的顶部.

如果在 statement 中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出 ReferenceError 异常。

var obj = {   a: 123,   b: 321, }; // 便捷写法 with (obj) {   var c = c; // ReferenceError } 复制代码

利与弊

那位微不足道的利

这里 with 括号中的值就是我们的公共对象,下面就是每个对象中的值

var a = obj.a; var b = obj.b; var c = obj.c; // 便捷写法 with (obj) {   var a = a;   var b = b;   var c = c; } 复制代码

var qs1 = location.search.substring(1); var hostname1 = location.hostname; var url1 = location.href; // 上面几行代码都包含了location对象,可使用with语句简写为以下形式 with (location) {   var qs2 = search.substring(1);   var hostname2 = hostname;   var url2 = href; } 复制代码

这样无疑会大大提高我们的效率(性能上却是一种丢失)

弊弊弊

  1. 意外创建全局变量

    with (obj) {   a = 2; } console.log(obj.a); // 输出 1 console.log(a); // 输出 2 复制代码

    这里的“输出 1”和“输出 2”的结果要看 obj 是否带有 a 这个属性。如果 obj 带有属性 a,那么会预期将 obj 的 a 属性赋予 2 的值,“输出 1”的结果为 2,“输出 2”会报错 a is not defined。如果 obj 不带有属性 a,我们可能会认为产生这样的效果 obj.a = 2,obj 将赋予属性 a 且 a 的值等于 2,但事实上并不会,而是会在全局作用域里创建一个全局变量 a,a 的值等于 2,也就是说,“输出 1”的结果为 undefined,“输出 2”的结果为 2。这种特性会意外地创建全局变量,从而污染全局作用域

  2. 语义不明

    当存在像以下这样的代码,如果我们不知道 b 里面有什么属性和方法,我们怎么知道 a 是 b 里的 a,还是 function 的入参 a 呢?

    function f(a, b) {   with (b) {     console.log(a);   } } 复制代码

  3. 性能丢失

    with (document.forms[0]) {   name.value = "lee king";   address.value = "Peking";   zipcode.value = "10000"; } // 可以看出 with 语句的简洁明了,不过在代码的世界里是很难找到真正的完美。 document.forms[0].name.value = "lee king"; document.forms[0].address.value = "Peking"; document.forms[0].zipcode.value = "10000"; 复制代码

    js 的解释器需要检查 with 块中的变量是否属于 with 包含的对象,没有的话作用域要关联到全局,这将使 with 语句执行速度大大下降,并且导致 js 语句很难被优化。所以在以后的高效代码开发中我们应该尽可能的避免使用 with 语句。

最后

with 语句就是一个没卵用的语句,w3school 和 MDN 都明确不推荐使用。在 js 的严格模式下,with 语句甚至是完全禁用的。


作者:余小力
链接:https://juejin.cn/post/7018821469840867336


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐