10

我能找到的几乎所有记录资源with都警告不要使用它,主要是因为如果未定义变量,它可能会产生不可预知的影响。

我想理解它,这样我就可以有效地利用它——毕竟,它的存在是有原因的。甚至eval有它的非邪恶用途!

所以,考虑到这一点,假设我想从一个元素中删除所有子节点,而不使用elem.innerHTML = "";

以下是安全的吗?

with(elem) while(firstChild) removeChild(firstChild);

请注意,此时我不关心可读性,只关心功能。既然firstChild是所有元素节点的属性和removeChild方法,那么使用with这种方式应该没问题,对吧?

同样,假设我想设置一些样式。

with(elem.style) {
    color = "red";
    backgroundColor = "black";
    fontWeight = "bold";
}

由于所有这些都是样式对象的属性(即使没有在样式表中定义,它们也作为空字符串存在),这样使用就可以with了,对吧?

我是否遗漏了什么,或者是不断警告不要使用with类似于针对 PHPmysql扩展的警告:防止愚蠢的程序员?

4

4 回答 4

4

Javascript 中的with关键字有点倒退到 90 年代后期它与 VBScript 竞争的时候。它仍然存在,但如果你'use strict';认为几乎每个 Javascript 验证器都存在错误,它就会被禁用。

它有两个主要问题,都与 JavaScript 中作用域的工作方式有关:

var color = "green";
var foo = "bar";

with(elem.style) {
    color = "red";
    foo = "something else";
}

现在是什么color情况?是什么foo?这不仅是令人困惑的代码,而且由于 Javascript 在with范围内查找变量的方式,它也是非常慢的代码,因为现在每个语句都有一个额外的范围来搜索每个使用的变量。

这是 jQuery 和 Prototype 等现代框架使用链接的原因之一。他们使用calland applyon 函数来控制this代表什么,这意味着您调用this.something而不是with(this){something}.

所以回答你的问题:withJavascript 有一个很好的用途——允许 90 年代编写的 IE4 和 IE5 网站今天仍然可以工作。

而已。您不应该在新代码中使用它。

于 2013-06-25T12:47:07.703 回答
1

唯一安全的使用with是根本不使用它。没有它就没有任何任务无法完成,现代标准在严格模式下完全禁用它。

出于所有目的,它被认为是一个设计错误,仅为了向后兼容而保留。

于 2013-06-25T12:40:38.127 回答
0

with只需将变量放在搜索变量的“地图”堆栈的顶部。

普通堆栈是(从上到下搜索)

  • 窗户
  • (根 - 只是有window

所以如果你有

var foo = { document: "doc.pdf" };
window.myFunc = function(){
    with( foo ){
        alert( document );
    }
}

里面的堆栈with

  • 窗户
  • (根 - 只是有window

它肯定会打印foo.document而不是window.document.

在这种情况下,很明显您不应该那样使用document,因为它通常用于浏览器。但是 ECMAScript 规范并没有定义这一点,所以在其他环境中,其他变量可能默认在堆栈上(甚至更多)。

危险在于,您在with语句中调用的任何内容也都在堆栈中。这将在document.url通话中失败:

// Some 3rd-party library
function redirect( url ){
    document.url = url;    // url is undefined in document
}

var bar = { document: "20x20" };

with( bar ){
    redirect(); //
}
于 2013-06-25T12:19:22.263 回答
0

with语句只是编写对对象的重复访问的简写:

为了

foobar.foo.bar.baz = 'bubu';
foobar.foo.bar.buz = 'baba';

你可以写

with(foobar.foo.bar){
    baz = 'bubu';
    buz = 'baba';
}

那很好!但是 foobar.foo.bar 会被修改还是全局变量 baz 和 buz 会被修改?在某些情况下,无法确定。

JavaScript 提供了更好的选择

var better = foobar.foo.bar;
better.baz = 'bubu';
better.buz = 'baba';

现在没有歧义了。

于 2013-06-25T12:46:16.327 回答