javascript中的"with"关键字

Joh*_*lum 48 javascript

可能重复:
JavaScript的"with"语句是否有合法用途?

我最近发现在javascript中,可以执行以下操作:

with document{
    write('foo');
    body.scrollTop = x;
}
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是需要检查每个变量以查看它是否属于文档对象,从而产生显着的开销.

或者,可以做这样的事情:

var d = document;
d.write('foo');
d.body.scrollTop = x;
Run Code Online (Sandbox Code Playgroud)

是否有任何情况下使用'with'关键字是合理的?

小智 71

只是不要使用它:http: //yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/

JavaScript的with声明旨在提供写入对象的重复访问的简写.所以不要写作

ooo.eee.oo.ah_ah.ting.tang.walla.walla.bing = true;
ooo.eee.oo.ah_ah.ting.tang.walla.walla.bang = true;
Run Code Online (Sandbox Code Playgroud)

你可以写

with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) {
    bing = true;
    bang = true;
}
Run Code Online (Sandbox Code Playgroud)

这看起来好多了.除了一件事.你无法通过查看代码来判断bingbang修改代码.会ooo.eee.oo.ah_ah.ting.tang.walla.walla被修改吗?或将全局变量bingbang得到打一顿?不可能确切地知道......

如果您无法阅读某个程序并确信您知道它将要执行的操作,那么您就不能确信它能够正常工作.因此,with应该避免陈述......

  • 例如,Visual Basic.NET正确,http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx,它们强制您为属于范围对象的所有标识符添加前缀一个点. (4认同)
  • 我无法表达这一点:任何"with"类似的语法,如JavaScript和Delphi的语法,你没有明确指定哪些标识符属于"作用域"对象,哪些不是,**evil**,请勿在这些语言中使用该语法.特别是,未来的更改可能会在没有警告的情况下更改该代码的行为.如果这不是一个等待发生的错误,那么我不知道是什么. (2认同)
  • @John:我能找到的唯一理由是代码在使用时变得更清晰。如果你发现自己处于这种情况,你可以使用它...... (2认同)

Ric*_*ich 17

尽管几乎在所有地方都有相反的建议,但我认为有"with"的用途.例如,我正在研究Javascript的域模型框架,它使用下划线字符,就像jQuery使用"$"一样.这意味着如果没有"with",我会在代码中散布许多下划线,这些下划线会降低其可读性.这是使用框架的应用程序的随机行:

_.People().sort(_.score(_.isa(_.Parent)),'Surname','Forename');
Run Code Online (Sandbox Code Playgroud)

而"with"则看起来像

with (_) {
    ...

    People().sort(score(isa(Parent)),'Surname','Forename');

    ...
}
Run Code Online (Sandbox Code Playgroud)

真正有用的是"with"的只读版本.

  • 这些天,通过ES6对象解构,您可以改为`const {People,score,isa,Parent} = _;`,而不会带来`with(_)`的所有恶劣风险. (11认同)

med*_*iev 5

我会避免在生产代码中使用它,因为它含糊不清但是通过使用with模仿let绑定有一个替代解决for-loop-closure解决方案,这里是我以前的答案的副本:

使用for循环内部函数的标准闭包解决方案的替代方法:

<a  href="#">blah</a><br>
<a  href="#">blah</a><br>
<a  href="#">foo</a><br>
<script>
    (function() {
    var anchors = document.getElementsByTagName('a');
        for ( var i = anchors.length; i--; ) {
            var link = anchors[i];
            with ({ number: i }) {
                link.onclick = function() {
                    alert(number);
                };
            }
        }
    })();
</script>
Run Code Online (Sandbox Code Playgroud)

感谢nlogax提供我几乎扯下一个解决方案: 使用Javascript臭名昭著的循环问题?

这是标准解决方案:

<script>
    (function() {
    var anchors = document.getElementsByTagName('a');
    for ( var i = anchors.length; i--; ) {
        var link = anchors[i];
        (function(i) {
            link.onclick = function() {
                alert(i)
            }
        })(i);
    }
    })();
</script>
Run Code Online (Sandbox Code Playgroud)

  • 请确保您说明哪个部分是"模棱两可的",因为JavaScript解释器和/或编译器从不混淆用于标识符的内容.这是未来的变化和/或程序员可能解释标识符的问题. (2认同)