Alan Storm's comments in response to my answer regarding the with
statement got me thinking. I've seldom found a reason to use this particular language feature, and had never given much thought to how it might cause trouble. Now, I'm curious as to how I might make effective use of with
, while avoiding its pitfalls.
Alan Storm对我的回答的回应让我思考。我很少找到使用这种语言特性的理由,而且从来没有考虑过它会如何引起麻烦。现在,我很好奇,我如何能有效地利用它,同时避免它的陷阱。
Where have you found the with
statement useful?
你在哪里找到有用的语句?
31 个解决方案
#1
505
Another use occurred to me today, so I searched the web excitedly and found an existing mention of it: Defining Variables inside Block Scope.
今天我又想到了另一个用法,所以我兴奋地搜索了一下网络,发现了一个已经存在的问题:在块范围内定义变量。
Background
JavaScript, in spite of its superficial resemblance to C and C++, does not scope variables to the block they are defined in:
尽管JavaScript与C和c++表面上很相似,但它并没有将变量定义为:
var name = "Joe";
if ( true )
{
var name = "Jack";
}
// name now contains "Jack"
Declaring a closure in a loop is a common task where this can lead to errors:
在循环中声明闭包是一个常见的任务,这会导致错误:
for (var i=0; i<3; ++i)
{
var num = i;
setTimeout(function() { alert(num); }, 10);
}
Because the for loop does not introduce a new scope, the same num
- with a value of 2
- will be shared by all three functions.
因为for循环没有引入新的作用域,相同的num(值为2)将由所有三个函数共享。
A new scope: let
and with
With the introduction of the let
statement in ES6, it becomes easy to introduce a new scope when necessary to avoid these problems:
在ES6中引入let语句之后,为了避免这些问题,很容易引入一个新的范围:
// variables introduced in this statement
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
setTimeout(function() { alert(i); }, 10);
}
Or even:
甚至:
for (var i=0; i<3; ++i)
{
// variables introduced in this statement
// are scoped to the block containing it.
let num = i;
setTimeout(function() { alert(num); }, 10);
}
Until ES6 is universally available, this use remains limited to the newest browsers and developers willing to use transpilers. However, we can easily simulate this behavior using with
:
在ES6普遍可用之前,这种用法仅限于最新的浏览器和愿意使用传输器的开发人员。然而,我们可以很容易地模拟这种行为:
for (var i=0; i<3; ++i)
{
// object members introduced in this statement
// are scoped to the block following it.
with ({num: i})
{
setTimeout(function() { alert(num); }, 10);
}
}
The loop now works as intended, creating three separate variables with values from 0 to 2. Note that variables declared within the block are not scoped to it, unlike the behavior of blocks in C++ (in C, variables must be declared at the start of a block, so in a way it is similar). This behavior is actually quite similar to a let
block syntax introduced in earlier versions of Mozilla browsers, but not widely adopted elsewhere.
这个循环现在按预期工作,创建三个独立的变量,值从0到2。注意,在块中声明的变量并没有作用于它,不像c++中的块行为(在C中,变量必须在块开始时声明,所以在某种程度上它是相似的)。这种行为实际上非常类似于早期版本的Mozilla浏览器中引入的let块语法,但在其他地方并没有广泛采用。
#2
155
I have been using the with statement as a simple form of scoped import. Let's say you have a markup builder of some sort. Rather than writing:
我一直使用with语句作为范围导入的一种简单形式。假设你有一个某种标记生成器。而不是写:
markupbuilder.div(
markupbuilder.p('Hi! I am a paragraph!',
markupbuilder.span('I am a span inside a paragraph')
)
)
You could instead write:
你可以写:
with(markupbuilder){
div(
p('Hi! I am a paragraph!',
span('I am a span inside a paragraph')
)
)
}
For this use case, I am not doing any assignment, so I don't have the ambiguity problem associated with that.
对于这个用例,我没有做任何赋值,所以我没有与此相关的模糊性问题。
#3
81
As my previous comments indicated, I don't think you can use with
safely no matter how tempting it might be in any given situation. Since the issue isn't directly covered here, I'll repeat it. Consider the following code
正如我先前的评论所指出的,我认为无论在任何情况下,你都不能安全地使用它。既然这个问题没有直接在这里讨论,我就重复一遍。考虑下面的代码
user = {};
someFunctionThatDoesStuffToUser(user);
someOtherFunction(user);
with(user){
name = 'Bob';
age = 20;
}
Without carefully investigating those function calls, there's no way to tell what the state of your program will be after this code runs. If user.name
was already set, it will now be Bob
. If it wasn't set, the global name
will be initialized or changed to Bob
and the user
object will remain without a name
property.
如果不仔细研究这些函数调用,就无法知道代码运行后程序的状态。如果用户名已经设置好了,那么现在就是Bob。如果没有设置,全局名称将被初始化或更改为Bob,而用户对象将保持没有名称属性。
Bugs happen. If you use with you will eventually do this and increase the chances your program will fail. Worse, you may encounter working code that sets a global in the with block, either deliberately or through the author not knowing about this quirk of the construct. It's a lot like encountering fall through on a switch, you have no idea if the author intended this and there's no way to know if "fixing" the code will introduce a regression.
错误发生。如果你和你一起使用,最终会这样做,增加你的程序失败的机会。更糟糕的是,您可能会遇到一些工作代码,这些代码将全局设置为带有块的,要么是故意的,要么是通过作者不知道构造的这个怪癖。这很像在一个开关上遭遇失败,你不知道作者是否打算这样做,并且没有办法知道“修复”代码是否会引入回归。
Modern programming languages are chocked full of features. Some features, after years of use, are discovered to be bad, and should be avoided. Javascript's with
is one of them.
现代编程语言充满了各种特性。一些特征,经过多年的使用,被发现是坏的,并且应该被避免。Javascript是其中之一。
#4
63
I actually found the with
statement to be incredibly useful recently. This technique never really occurred to me until I started my current project - a command line console written in JavaScript. I was trying to emulate the Firebug/WebKit console APIs where special commands can be entered into the console but they don't override any variables in the global scope. I thought of this when trying to overcome a problem I mentioned in the comments to Shog9's excellent answer.
事实上,我最近发现这个声明非常有用。直到我启动了当前的项目——用JavaScript编写的命令行控制台,我才真正意识到这种技术。我试图模拟Firebug/WebKit控制台api,其中特殊的命令可以被输入到控制台,但是它们不会覆盖全局范围内的任何变量。在试图解决我在Shog9的精彩回答中提到的一个问题时,我想到了这一点。
To achieve this effect, I used two with statements to "layer" a scope behind the global scope:
为了达到这个效果,我使用了两个语句来“层”在全局范围后面的范围:
with (consoleCommands) {
with (window) {
eval(expression);
}
}
The great thing about this technique is that, aside from the performance disadvantages, it doesn't suffer the usual fears of the with
statement, because we're evaluating in the global scope anyway - there's no danger of variables outside our pseudo-scope from being modified.
这种技术的优点在于,除了性能上的缺点,它不会像一般的语句那样受到人们的恐惧,因为我们在全局范围内进行评估——在我们的伪范围之外没有任何变量的危险被修改。
I was inspired to post this answer when, to my surprise, I managed to find the same technique used elsewhere - the Chromium source code!
当我惊讶地发现,我在其他地方找到了同样的技术——铬的源代码!
InjectedScript._evaluateOn = function(evalFunction, object, expression) {
InjectedScript._ensureCommandLineAPIInstalled();
// Surround the expression in with statements to inject our command line API so that
// the window object properties still take more precedent than our API functions.
expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
return evalFunction.call(object, expression);
}
EDIT: Just checked the Firebug source, they chain 4 with statements together for even more layers. Crazy!
编辑:刚刚检查了Firebug的源代码,他们将4条语句连接在一起,以获得更多的层。疯了!
const evalScript = "with (__win__.__scope__.vars) { with (__win__.__scope__.api) { with (__win__.__scope__.userVars) { with (__win__) {" +
"try {" +
"__win__.__scope__.callback(eval(__win__.__scope__.expr));" +
"} catch (exc) {" +
"__win__.__scope__.callback(exc, true);" +
"}" +
"}}}}";
#5
53
Yes, yes and yes. There is a very legitimate use. Watch:
是的,是的,是的。有一个非常合法的用途。看:
with (document.getElementById("blah").style) {
background = "black";
color = "blue";
border = "1px solid green";
}
Basically any other DOM or CSS hooks are fantastic uses of with. It's not like "CloneNode" will be undefined and go back to the global scope unless you went out of your way and decided to make it possible.
基本上,任何其他的DOM或CSS钩子都是非常有用的。它不像“CloneNode”是没有定义的,回到全局的范围,除非你离开你的方式,并决定让它成为可能。
Crockford's speed complaint is that a new context is created by with. Contexts are generally expensive. I agree. But if you just created a div and don't have some framework on hand for setting your css and need to set up 15 or so CSS properties by hand, then creating a context will probably be cheaper then variable creation and 15 dereferences:
Crockford的速度抱怨是一个新的环境被创造出来。上下文通常是昂贵的。我同意。但是,如果你只是创建了一个div,并且没有现成的框架来设置你的css,并且需要手工设置15个css属性,那么创建一个context可能会更便宜,然后是变量创建和15个dereferences:
var element = document.createElement("div"),
elementStyle = element.style;
elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";
etc...
等等……
#6
33
You can define a small helper function to provide the benefits of with
without the ambiguity:
您可以定义一个小的helper函数来提供无歧义的好处:
var with_ = function (obj, func) { func (obj); };
with_ (object_name_here, function (_)
{
_.a = "foo";
_.b = "bar";
});
#7
25
Hardly seems worth it since you can do the following:
这似乎不值得,因为你可以做到以下几点:
var o = incrediblyLongObjectNameThatNoOneWouldUse;
o.name = "Bob";
o.age = "50";
#8
18
I don't ever use with, don't see a reason to, and don't recommend it.
我从来没有使用过,也没有理由去使用它,也不要推荐它。
The problem with with
is that it prevents numerous lexical optimizations an ECMAScript implementation can perform. Given the rise of fast JIT-based engines, this issue will probably become even more important in the near future.
问题在于它阻止了大量的词汇优化,ECMAScript实现可以执行。考虑到基于快速抖动的引擎的崛起,这个问题在不久的将来可能会变得更加重要。
It might look like with
allows for cleaner constructs (when, say, introducing a new scope instead of a common anonymous function wrapper or replacing verbose aliasing), but it's really not worth it. Besides a decreased performance, there's always a danger of assigning to a property of a wrong object (when property is not found on an object in injected scope) and perhaps erroneously introducing global variables. IIRC, latter issue is the one that motivated Crockford to recommend to avoid with
.
它可能看起来像允许使用更干净的结构(比如,当引入一个新的范围而不是一个普通的匿名函数包装器或者替换冗长的别名),但是它真的不值得。除了性能下降之外,总是存在分配错误对象的属性的危险(当在注入的范围内没有发现属性时),并且可能错误地引入全局变量。IIRC,后者的问题是促使Crockford建议避免使用的。
#9
14
Visual Basic.NET has a similar With
statement. One of the more common ways I use it is to quickly set a number of properties. Instead of:
Visual Basic。NET与语句有相似之处。我使用它的一个比较常见的方法是快速设置一些属性。而不是:
someObject.Foo = ''
someObject.Bar = ''
someObject.Baz = ''
, I can write:
我可以写:
With someObject
.Foo = ''
.Bar = ''
.Baz = ''
End With
This isn't just a matter of laziness. It also makes for much more readable code. And unlike JavaScript, it does not suffer from ambiguity, as you have to prefix everything affected by the statement with a .
(dot). So, the following two are clearly distinct:
这不仅仅是懒惰的问题。它也使得代码更加可读。与JavaScript不同的是,它不会受到歧义的影响,因为你必须在语句的前面加上前缀a。(点)。所以,下面两个是明显不同的:
With someObject
.Foo = ''
End With
vs.
vs。
With someObject
Foo = ''
End With
The former is someObject.Foo
; the latter is Foo
in the scope outside someObject
.
前者是someObject.Foo;后者是在某个对象之外的范围内的Foo。
I find that JavaScript's lack of distinction makes it far less useful than Visual Basic's variant, as the risk of ambiguity is too high. Other than that, with
is still a powerful idea that can make for better readability.
我发现JavaScript的缺乏区分使得它远不如Visual Basic的变体有用,因为含糊的风险太高了。除此之外,它仍然是一个强大的想法,可以提高可读性。
#10
7
Using "with" can make your code more dry.
使用“with”可以使您的代码更加干燥。
Consider the following code:
考虑下面的代码:
var photo = document.getElementById('photo');
photo.style.position = 'absolute';
photo.style.left = '10px';
photo.style.top = '10px';
You can dry it to the following:
你可以把它擦干:
with(document.getElementById('photo').style) {
position = 'absolute';
left = '10px';
top = '10px';
}
I guess it depends whether you have a preference for legibility or expressiveness.
我想这取决于你对易读性和表达性的偏好。
The first example is more legible and probably recommended for most code. But most code is pretty tame anyway. The second one is a bit more obscure but uses the expressive nature of the language to cut down on code size and superfluous variables.
第一个示例更清晰,可能推荐大多数代码。但是大多数代码还是很驯服的。第二种方法稍微有些晦涩,但是它使用了语言的表达性来减少代码的大小和多余的变量。
I imagine people who like Java or C# would choose the first way (object.member) and those who prefer Ruby or Python would choose the latter.
我想,喜欢Java或c#的人会选择第一种方式(object.member),而喜欢Ruby或Python的人会选择后者。
#11
7
You can use with
to introduce the contents of an object as local variables to a block, like it's being done with this small template engine.
您可以将对象的内容作为局部变量引入到块中,就像使用这个小模板引擎一样。
#12
5
I think the obvious use is as a shortcut. If you're e.g. initializing an object you simply save typing a lot of "ObjectName." Kind of like lisp's "with-slots" which lets you write
我认为最明显的用法是作为捷径。如果您正在初始化一个对象,那么您只需保存大量的“ObjectName”。有点像lisp的“带槽”,可以让你写。
(with-slots (foo bar) objectname
"some code that accesses foo and bar"
which is the same as writing
这和写作是一样的吗?
"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""
It's more obvious why this is a shortcut then when your language allows "Objectname.foo" but still.
更明显的是,当您的语言允许“Objectname”时,这是一个快捷方式。foo”但仍然。
#13
5
Having experience with Delphi, I would say that using with should be a last-resort size optimization, possibly performed by some kind of javascript minimizer algorithm with access to static code analysis to verify its safety.
有了Delphi的经验,我想说,使用应该是最后的规模优化,可能是通过某种javascript最小化算法来实现静态代码分析,以验证其安全性。
The scoping problems you can get into with liberal use of the with statement can be a royal pain in the a** and I wouldn't want anyone to experience a debugging session to figure out what the he.. is going on in your code, only to find out that it captured an object member or the wrong local variable, instead of your global or outer scope variable which you intended.
你可以*使用的范围内的问题可以是一个**的皇家痛苦,我不想让任何人经历一个调试过程来弄清楚他到底是什么。在您的代码中,只发现它捕获了一个对象成员或错误的局部变量,而不是您想要的全局变量或外部范围变量。
The VB with statement is better, in that it needs the dots to disambiguate the scoping, but the Delphi with statement is a loaded gun with a hairtrigger, and it looks to me as though the javascript one is similar enough to warrant the same warning.
带有语句的VB更好,因为它需要点来消除scoping的歧义,但是带有语句的Delphi是带有一个发夹的上膛的枪,它在我看来就好像javascript一样,足以发出同样的警告。
#14
4
The with statement can be used to decrease the code size or for private class members, example:
可以使用with语句来减少代码大小或为私有类成员,例如:
// demo class framework
var Class= function(name, o) {
var c=function(){};
if( o.hasOwnProperty("constructor") ) {
c= o.constructor;
}
delete o["constructor"];
delete o["prototype"];
c.prototype= {};
for( var k in o ) c.prototype[k]= o[k];
c.scope= Class.scope;
c.scope.Class= c;
c.Name= name;
return c;
}
Class.newScope= function() {
Class.scope= {};
Class.scope.Scope= Class.scope;
return Class.scope;
}
// create a new class
with( Class.newScope() ) {
window.Foo= Class("Foo",{
test: function() {
alert( Class.Name );
}
});
}
(new Foo()).test();
The with-statement is very usefull if you want to modify the scope, what is necessary for having your own global scope that you can manipulate at runtime. You can put constants on it or certain helper functions often used like e.g. "toUpper", "toLower" or "isNumber", "clipNumber" aso..
如果您想要修改范围,那么with-statement非常有用,您可以在运行时操作自己的全局范围。你可以在它上面加上常数或者某些辅助函数,比如。“toUpper”,“toLower”或“isNumber”,“clipNumber”
About the bad performance I read that often: Scoping a function won't have any impact on the performance, in fact in my FF a scoped function runs faster then an unscoped:
关于糟糕的性能,我经常读到这样的情况:对函数的定义不会对性能产生任何影响,事实上,在我的FF中,作用域的函数运行得更快,然后是一个未作用域:
var o={x: 5},r, fnRAW= function(a,b){ return a*b; }, fnScoped, s, e, i;
with( o ) {
fnScoped= function(a,b){ return a*b; };
}
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnRAW(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnScoped(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
So in the above mentioned way used the with-statement has no negative effect on performance, but a good one as it deceases the code size, what impacts the memory usage on mobile devices.
因此,在上述方法中使用with-statement对性能没有任何负面影响,但是很好,因为它欺骗了代码的大小,影响了移动设备上的内存使用。
#15
4
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
不推荐使用,在ECMAScript 5严格模式中禁用。推荐的替代方法是指定要访问临时变量的属性的对象。
来源:Mozilla.org
#16
2
Using with also makes your code slower in many implementation, as everything now gets wrapped in an extra scope for lookup. There's no legitimate reason for using with in JavaScript.
使用它还会使您的代码在许多实现中变得更慢,因为现在所有东西都被打包在一个额外的查找范围内。使用JavaScript没有合理的理由。
#17
2
I think that the usefulness of with
can be dependent on how well your code is written. For example, if you're writing code that appears like this:
我认为使用的有用性取决于你的代码写得有多好。例如,如果您编写的代码是这样的:
var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();
then you could argue that with
will improve the readability of the code by doing this:
然后你可以争辩说通过这样做可以提高代码的可读性:
var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
sHeader = header.toString();
sContent = content.toString();
sFooter = content.toString();
}
Conversely, it could be argued that you're violating the Law of Demeter, but, then again, maybe not. I digress =).
相反地,你可能会认为你违反了德墨忒尔定律,但是,也许不是。我跑题了=)。
Above all else, know that Douglas Crockford recommends not using with
. I urge you to check out his blog post regarding with
and its alternatives here.
最重要的是,要知道道格拉斯·克罗克福德建议不要使用。我强烈建议你去看看他的博客文章,看看有没有其他的选择。
#18
2
I think the with-statement can come in handy when converting a template language into JavaScript. For example JST in base2, but I've seen it more often.
我认为,当将模板语言转换为JavaScript时,with_statement会很有用。例如在base2中的JST,但是我经常看到它。
I agree one can program this without the with-statement. But because it doesn't give any problems it is a legitimate use.
我同意一个人可以在没有附带声明的情况下编程。但是因为它没有给任何问题,它是合法的使用。
#19
2
I think the object literal use is interesting, like a drop-in replacement for using a closure
我认为对象的字面用法很有趣,就像使用闭包的drop-in替换。
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
(function(info)
{
nodes[i].onclick = function(){ showStuff(info) };
})(data[i]);
}
or the with statement equivilent of a closure
或者是带有闭包的语句。
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
with({info: data[i]})
{
nodes[i].onclick = function(){ showStuff(info) };
}
}
I think the real risk is accidently minipulating variables that are not part of the with statement, which is why I like the object literal being passed into with, you can see exactly what it will be in the added context in the code.
我认为真正的风险是意外的缩小了的变量,而不是带有语句的部分,这就是为什么我喜欢将对象文字传递进来的原因,你可以看到在代码中添加的上下文中的具体内容。
#20
2
I created a "merge" function which eliminates some of this ambiguity with the with
statement:
我创建了一个“合并”函数,它消除了一些模棱两可的语句:
if (typeof Object.merge !== 'function') {
Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
for(var i in o2) { o1[i] = o2[i]; }
return o1;
};
}
I can use it similarly to with
, but I can know it won't affect any scope which I don't intend for it to affect.
我可以使用它,但我知道它不会影响任何我不打算影响的范围。
Usage:
用法:
var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
function NewObj() {
Object.merge(this, {size: 4096, initDate: new Date()});
}
#21
2
For some short code pieces, I would like to use the trigonometric functions like sin
, cos
etc. in degree mode instead of in radiant mode. For this purpose, I use an AngularDegree
object:
对于一些短小的代码片段,我想要使用诸如sin, cos等的三角函数,而不是在辐射模式下。为此,我使用了AngularDegreeobject:
AngularDegree = new function() {
this.CONV = Math.PI / 180;
this.sin = function(x) { return Math.sin( x * this.CONV ) };
this.cos = function(x) { return Math.cos( x * this.CONV ) };
this.tan = function(x) { return Math.tan( x * this.CONV ) };
this.asin = function(x) { return Math.asin( x ) / this.CONV };
this.acos = function(x) { return Math.acos( x ) / this.CONV };
this.atan = function(x) { return Math.atan( x ) / this.CONV };
this.atan2 = function(x,y) { return Math.atan2(x,y) / this.CONV };
};
Then I can use the trigonometric functions in degree mode without further language noise in a with
block:
然后,我可以在没有进一步语言噪声的情况下,在学位模式下使用三角函数:
function getAzimut(pol,pos) {
...
var d = pos.lon - pol.lon;
with(AngularDegree) {
var z = atan2( sin(d), cos(pol.lat)*tan(pos.lat) - sin(pol.lat)*cos(d) );
return z;
}
}
This means: I use an object as a collection of functions, which I enable in a limited code region for direct access. I find this useful.
这意味着:我使用一个对象作为函数的集合,我在一个有限的代码区域中允许直接访问。我觉得这很有用。
#22
1
I just really don't see how using the with is any more readable than just typing object.member. I don't think it's any less readable, but I don't think it's any more readable either.
我真的不知道如何使用它比只输入object.member更可读。我不认为它没有什么可读性,但我认为它也没有任何可读性。
Like lassevk said, I can definitely see how using with would be more error prone than just using the very explicit "object.member" syntax.
就像lassevk说的那样,我可以肯定地看到,与使用非常明确的“对象”相比,如何使用更容易出错。成员”语法。
#23
1
It's good for putting code that runs in a relatively complicated environment into a container: I use it to make a local binding for "window" and such to run code meant for a web browser.
将在相对复杂的环境中运行的代码放入容器中是很有好处的:我用它来为“窗口”做一个本地绑定,以及为web浏览器运行代码。
#24
1
You got to see the validation of a form in javascript at W3schools http://www.w3schools.com/js/js_form_validation.asp where the object form is "scanned" through to find an input with name 'email'
你可以在W3schools网站http://www.w3schools.com/js/js_form_valid. asp中看到一种表单的验证,该表单的对象表单被“扫描”,以找到一个名为“email”的输入
But i've modified it to get from ANY form all the fields validate as not empty, regardless of the name or quantity of field in a form. Well i've tested only text-fields.
但是我已经修改了它从任何形式的所有字段都验证为不空,而不考虑表单中字段的名称或数量。我只测试了文本字段。
But the with() made things simpler. Here's the code:
但是with()使事情变得更简单。这是代码:
function validate_required(field)
{
with (field)
{
if (value==null||value=="")
{
alert('All fields are mandtory');return false;
}
else
{
return true;
}
}
}
function validate_form(thisform)
{
with (thisform)
{
for(fiie in elements){
if (validate_required(elements[fiie])==false){
elements[fiie].focus();
elements[fiie].style.border='1px solid red';
return false;
} else {elements[fiie].style.border='1px solid #7F9DB9';}
}
}
return false;
}
#25
1
CoffeeScript's Coco fork has a with
keyword, but it simply sets this
(also writable as @
in CoffeeScript/Coco) to the target object within the block. This removes ambiguity and achieves ES5 strict mode compliance:
CoffeeScript的Coco fork有一个with关键字,但它只是将这个(也可写为@ in CoffeeScript/Coco)设置为block中的目标对象。这消除了歧义并实现了ES5严格的模式遵从性:
with long.object.reference
@a = 'foo'
bar = @b
#26
0
Here's a good use for with
: adding new elements to an Object Literal, based on values stored in that Object. Here's an example that I just used today:
这里有一个很好的用法:根据存储在对象中的值,将新元素添加到对象文本中。这是我今天使用的一个例子:
I had a set of possible tiles (with openings facing top, bottom, left, or right) that could be used, and I wanted a quick way of adding a list of tiles which would be always placed and locked at the start of the game. I didn't want to keep typing types.tbr
for each type in the list, so I just used with
.
我有一组可以使用的可能的瓦片(开口朝上、下、左或右),我想要一种快速的方法来添加一个方块列表,它总是在游戏开始时被放置和锁定。我不想继续打字。列表中的每一种类型的tbr,所以我只使用了。
Tile.types = (function(t,l,b,r) {
function j(a) { return a.join(' '); }
// all possible types
var types = {
br: j( [b,r]),
lbr: j([l,b,r]),
lb: j([l,b] ),
tbr: j([t,b,r]),
tbl: j([t,b,l]),
tlr: j([t,l,r]),
tr: j([t,r] ),
tl: j([t,l] ),
locked: []
};
// store starting (base/locked) tiles in types.locked
with( types ) { locked = [
br, lbr, lbr, lb,
tbr, tbr, lbr, tbl,
tbr, tlr, tbl, tbl,
tr, tlr, tlr, tl
] }
return types;
})("top","left","bottom","right");
#27
0
You can use with to avoid having to explicitly manage arity when using require.js:
在使用requires .js时,您可以使用它来避免显式地管理特性。
var modules = requirejs.declare([{
'App' : 'app/app'
}]);
require(modules.paths(), function() { with (modules.resolve(arguments)) {
App.run();
}});
Implementation of requirejs.declare:
requirejs.declare实现:
requirejs.declare = function(dependencyPairs) {
var pair;
var dependencyKeys = [];
var dependencyValues = [];
for (var i=0, n=dependencyPairs.length; i<n; i++) {
pair = dependencyPairs[i];
for (var key in dependencyPairs[i]) {
dependencyKeys.push(key);
dependencyValues.push(pair[key]);
break;
}
};
return {
paths : function() {
return dependencyValues;
},
resolve : function(args) {
var modules = {};
for (var i=0, n=args.length; i<n; i++) {
modules[dependencyKeys[i]] = args[i];
}
return modules;
}
}
}
#28
0
As Andy E pointed out in the comments of Shog9's answer, this potentially-unexpected behavior occurs when using with
with an object literal:
正如Andy E在Shog9的回答中指出的那样,这种潜在的意想不到的行为发生在使用对象文字时:
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with ({num: i}) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "[object Object]"
}
}
Not that unexpected behavior wasn't already a hallmark of with
.
并不是说这种意外的行为已经成为了我们的标志。
If you really still want to use this technique, at least use an object with a null prototype.
如果您仍然想使用这种技术,那么至少要使用一个具有空原型的对象。
function scope(o) {
var ret = Object.create(null);
if (typeof o !== 'object') return ret;
Object.keys(o).forEach(function (key) {
ret[key] = o[key];
});
return ret;
}
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with (scope({num: i})) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "a"
}
}
But this will only work in ES5+. Also don't use with
.
但这只适用于ES5+。也不要使用。
#29
0
I am working on a project that will allow users to upload code in order to modify the behavior of parts of the application. In this scenario, I have been using a with
clause to keep their code from modifying anything outside of the scope that I want them to mess around with. The (simplified) portion of code I use to do this is:
我正在做一个项目,允许用户上传代码,以修改应用程序的部分行为。在这个场景中,我使用了一个with子句来防止他们的代码修改超出我想要他们处理的范围之外的任何东西。我所使用的(简化的)代码部分是:
// this code is only executed once
var localScope = {
build: undefined,
// this is where all of the values I want to hide go; the list is rather long
window: undefined,
console: undefined,
...
};
with(localScope) {
build = function(userCode) {
eval('var builtFunction = function(options) {' + userCode + '}');
return builtFunction;
}
}
var build = localScope.build;
delete localScope.build;
// this is how I use the build method
var userCode = 'return "Hello, World!";';
var userFunction = build(userCode);
This code ensures (somewhat) that the user-defined code neither has access to any globally-scoped objects such as window
nor to any of my local variables through a closure.
该代码确保(某种程度上)用户定义的代码不能通过闭包访问任何全局范围的对象,例如窗口或任何本地变量。
Just as a word to the wise, I still have to perform static code checks on the user-submitted code to ensure they aren't using other sneaky manners to access global scope. For instance, the following user-defined code grabs direct access to window
:
对于明智的人来说,我仍然需要对用户提交的代码进行静态代码检查,以确保他们不会使用其他的鬼把戏来访问全局范围。例如,以下用户定义的代码可以直接访问窗口:
test = function() {
return this.window
};
return test();
#30
0
My
我的
switch(e.type) {
case gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED: blah
case gapi.drive.realtime.ErrorType.CLIENT_ERROR: blah
case gapi.drive.realtime.ErrorType.NOT_FOUND: blah
}
boils down to
可以归结为
with(gapi.drive.realtime.ErrorType) {switch(e.type) {
case TOKEN_REFRESH_REQUIRED: blah
case CLIENT_ERROR: blah
case NOT_FOUND: blah
}}
Can you trust so low-quality code? No, we see that it was made absolutely unreadable. This example undeniably proves that there is no need for with-statement, if I am taking readability right ;)
你能相信如此低质量的代码吗?不,我们看到它是绝对不可读的。这个例子不可否认地证明了,如果我是正确的,就不需要用with-statement。
#1
505
Another use occurred to me today, so I searched the web excitedly and found an existing mention of it: Defining Variables inside Block Scope.
今天我又想到了另一个用法,所以我兴奋地搜索了一下网络,发现了一个已经存在的问题:在块范围内定义变量。
Background
JavaScript, in spite of its superficial resemblance to C and C++, does not scope variables to the block they are defined in:
尽管JavaScript与C和c++表面上很相似,但它并没有将变量定义为:
var name = "Joe";
if ( true )
{
var name = "Jack";
}
// name now contains "Jack"
Declaring a closure in a loop is a common task where this can lead to errors:
在循环中声明闭包是一个常见的任务,这会导致错误:
for (var i=0; i<3; ++i)
{
var num = i;
setTimeout(function() { alert(num); }, 10);
}
Because the for loop does not introduce a new scope, the same num
- with a value of 2
- will be shared by all three functions.
因为for循环没有引入新的作用域,相同的num(值为2)将由所有三个函数共享。
A new scope: let
and with
With the introduction of the let
statement in ES6, it becomes easy to introduce a new scope when necessary to avoid these problems:
在ES6中引入let语句之后,为了避免这些问题,很容易引入一个新的范围:
// variables introduced in this statement
// are scoped to each iteration of the loop
for (let i=0; i<3; ++i)
{
setTimeout(function() { alert(i); }, 10);
}
Or even:
甚至:
for (var i=0; i<3; ++i)
{
// variables introduced in this statement
// are scoped to the block containing it.
let num = i;
setTimeout(function() { alert(num); }, 10);
}
Until ES6 is universally available, this use remains limited to the newest browsers and developers willing to use transpilers. However, we can easily simulate this behavior using with
:
在ES6普遍可用之前,这种用法仅限于最新的浏览器和愿意使用传输器的开发人员。然而,我们可以很容易地模拟这种行为:
for (var i=0; i<3; ++i)
{
// object members introduced in this statement
// are scoped to the block following it.
with ({num: i})
{
setTimeout(function() { alert(num); }, 10);
}
}
The loop now works as intended, creating three separate variables with values from 0 to 2. Note that variables declared within the block are not scoped to it, unlike the behavior of blocks in C++ (in C, variables must be declared at the start of a block, so in a way it is similar). This behavior is actually quite similar to a let
block syntax introduced in earlier versions of Mozilla browsers, but not widely adopted elsewhere.
这个循环现在按预期工作,创建三个独立的变量,值从0到2。注意,在块中声明的变量并没有作用于它,不像c++中的块行为(在C中,变量必须在块开始时声明,所以在某种程度上它是相似的)。这种行为实际上非常类似于早期版本的Mozilla浏览器中引入的let块语法,但在其他地方并没有广泛采用。
#2
155
I have been using the with statement as a simple form of scoped import. Let's say you have a markup builder of some sort. Rather than writing:
我一直使用with语句作为范围导入的一种简单形式。假设你有一个某种标记生成器。而不是写:
markupbuilder.div(
markupbuilder.p('Hi! I am a paragraph!',
markupbuilder.span('I am a span inside a paragraph')
)
)
You could instead write:
你可以写:
with(markupbuilder){
div(
p('Hi! I am a paragraph!',
span('I am a span inside a paragraph')
)
)
}
For this use case, I am not doing any assignment, so I don't have the ambiguity problem associated with that.
对于这个用例,我没有做任何赋值,所以我没有与此相关的模糊性问题。
#3
81
As my previous comments indicated, I don't think you can use with
safely no matter how tempting it might be in any given situation. Since the issue isn't directly covered here, I'll repeat it. Consider the following code
正如我先前的评论所指出的,我认为无论在任何情况下,你都不能安全地使用它。既然这个问题没有直接在这里讨论,我就重复一遍。考虑下面的代码
user = {};
someFunctionThatDoesStuffToUser(user);
someOtherFunction(user);
with(user){
name = 'Bob';
age = 20;
}
Without carefully investigating those function calls, there's no way to tell what the state of your program will be after this code runs. If user.name
was already set, it will now be Bob
. If it wasn't set, the global name
will be initialized or changed to Bob
and the user
object will remain without a name
property.
如果不仔细研究这些函数调用,就无法知道代码运行后程序的状态。如果用户名已经设置好了,那么现在就是Bob。如果没有设置,全局名称将被初始化或更改为Bob,而用户对象将保持没有名称属性。
Bugs happen. If you use with you will eventually do this and increase the chances your program will fail. Worse, you may encounter working code that sets a global in the with block, either deliberately or through the author not knowing about this quirk of the construct. It's a lot like encountering fall through on a switch, you have no idea if the author intended this and there's no way to know if "fixing" the code will introduce a regression.
错误发生。如果你和你一起使用,最终会这样做,增加你的程序失败的机会。更糟糕的是,您可能会遇到一些工作代码,这些代码将全局设置为带有块的,要么是故意的,要么是通过作者不知道构造的这个怪癖。这很像在一个开关上遭遇失败,你不知道作者是否打算这样做,并且没有办法知道“修复”代码是否会引入回归。
Modern programming languages are chocked full of features. Some features, after years of use, are discovered to be bad, and should be avoided. Javascript's with
is one of them.
现代编程语言充满了各种特性。一些特征,经过多年的使用,被发现是坏的,并且应该被避免。Javascript是其中之一。
#4
63
I actually found the with
statement to be incredibly useful recently. This technique never really occurred to me until I started my current project - a command line console written in JavaScript. I was trying to emulate the Firebug/WebKit console APIs where special commands can be entered into the console but they don't override any variables in the global scope. I thought of this when trying to overcome a problem I mentioned in the comments to Shog9's excellent answer.
事实上,我最近发现这个声明非常有用。直到我启动了当前的项目——用JavaScript编写的命令行控制台,我才真正意识到这种技术。我试图模拟Firebug/WebKit控制台api,其中特殊的命令可以被输入到控制台,但是它们不会覆盖全局范围内的任何变量。在试图解决我在Shog9的精彩回答中提到的一个问题时,我想到了这一点。
To achieve this effect, I used two with statements to "layer" a scope behind the global scope:
为了达到这个效果,我使用了两个语句来“层”在全局范围后面的范围:
with (consoleCommands) {
with (window) {
eval(expression);
}
}
The great thing about this technique is that, aside from the performance disadvantages, it doesn't suffer the usual fears of the with
statement, because we're evaluating in the global scope anyway - there's no danger of variables outside our pseudo-scope from being modified.
这种技术的优点在于,除了性能上的缺点,它不会像一般的语句那样受到人们的恐惧,因为我们在全局范围内进行评估——在我们的伪范围之外没有任何变量的危险被修改。
I was inspired to post this answer when, to my surprise, I managed to find the same technique used elsewhere - the Chromium source code!
当我惊讶地发现,我在其他地方找到了同样的技术——铬的源代码!
InjectedScript._evaluateOn = function(evalFunction, object, expression) {
InjectedScript._ensureCommandLineAPIInstalled();
// Surround the expression in with statements to inject our command line API so that
// the window object properties still take more precedent than our API functions.
expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
return evalFunction.call(object, expression);
}
EDIT: Just checked the Firebug source, they chain 4 with statements together for even more layers. Crazy!
编辑:刚刚检查了Firebug的源代码,他们将4条语句连接在一起,以获得更多的层。疯了!
const evalScript = "with (__win__.__scope__.vars) { with (__win__.__scope__.api) { with (__win__.__scope__.userVars) { with (__win__) {" +
"try {" +
"__win__.__scope__.callback(eval(__win__.__scope__.expr));" +
"} catch (exc) {" +
"__win__.__scope__.callback(exc, true);" +
"}" +
"}}}}";
#5
53
Yes, yes and yes. There is a very legitimate use. Watch:
是的,是的,是的。有一个非常合法的用途。看:
with (document.getElementById("blah").style) {
background = "black";
color = "blue";
border = "1px solid green";
}
Basically any other DOM or CSS hooks are fantastic uses of with. It's not like "CloneNode" will be undefined and go back to the global scope unless you went out of your way and decided to make it possible.
基本上,任何其他的DOM或CSS钩子都是非常有用的。它不像“CloneNode”是没有定义的,回到全局的范围,除非你离开你的方式,并决定让它成为可能。
Crockford's speed complaint is that a new context is created by with. Contexts are generally expensive. I agree. But if you just created a div and don't have some framework on hand for setting your css and need to set up 15 or so CSS properties by hand, then creating a context will probably be cheaper then variable creation and 15 dereferences:
Crockford的速度抱怨是一个新的环境被创造出来。上下文通常是昂贵的。我同意。但是,如果你只是创建了一个div,并且没有现成的框架来设置你的css,并且需要手工设置15个css属性,那么创建一个context可能会更便宜,然后是变量创建和15个dereferences:
var element = document.createElement("div"),
elementStyle = element.style;
elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";
etc...
等等……
#6
33
You can define a small helper function to provide the benefits of with
without the ambiguity:
您可以定义一个小的helper函数来提供无歧义的好处:
var with_ = function (obj, func) { func (obj); };
with_ (object_name_here, function (_)
{
_.a = "foo";
_.b = "bar";
});
#7
25
Hardly seems worth it since you can do the following:
这似乎不值得,因为你可以做到以下几点:
var o = incrediblyLongObjectNameThatNoOneWouldUse;
o.name = "Bob";
o.age = "50";
#8
18
I don't ever use with, don't see a reason to, and don't recommend it.
我从来没有使用过,也没有理由去使用它,也不要推荐它。
The problem with with
is that it prevents numerous lexical optimizations an ECMAScript implementation can perform. Given the rise of fast JIT-based engines, this issue will probably become even more important in the near future.
问题在于它阻止了大量的词汇优化,ECMAScript实现可以执行。考虑到基于快速抖动的引擎的崛起,这个问题在不久的将来可能会变得更加重要。
It might look like with
allows for cleaner constructs (when, say, introducing a new scope instead of a common anonymous function wrapper or replacing verbose aliasing), but it's really not worth it. Besides a decreased performance, there's always a danger of assigning to a property of a wrong object (when property is not found on an object in injected scope) and perhaps erroneously introducing global variables. IIRC, latter issue is the one that motivated Crockford to recommend to avoid with
.
它可能看起来像允许使用更干净的结构(比如,当引入一个新的范围而不是一个普通的匿名函数包装器或者替换冗长的别名),但是它真的不值得。除了性能下降之外,总是存在分配错误对象的属性的危险(当在注入的范围内没有发现属性时),并且可能错误地引入全局变量。IIRC,后者的问题是促使Crockford建议避免使用的。
#9
14
Visual Basic.NET has a similar With
statement. One of the more common ways I use it is to quickly set a number of properties. Instead of:
Visual Basic。NET与语句有相似之处。我使用它的一个比较常见的方法是快速设置一些属性。而不是:
someObject.Foo = ''
someObject.Bar = ''
someObject.Baz = ''
, I can write:
我可以写:
With someObject
.Foo = ''
.Bar = ''
.Baz = ''
End With
This isn't just a matter of laziness. It also makes for much more readable code. And unlike JavaScript, it does not suffer from ambiguity, as you have to prefix everything affected by the statement with a .
(dot). So, the following two are clearly distinct:
这不仅仅是懒惰的问题。它也使得代码更加可读。与JavaScript不同的是,它不会受到歧义的影响,因为你必须在语句的前面加上前缀a。(点)。所以,下面两个是明显不同的:
With someObject
.Foo = ''
End With
vs.
vs。
With someObject
Foo = ''
End With
The former is someObject.Foo
; the latter is Foo
in the scope outside someObject
.
前者是someObject.Foo;后者是在某个对象之外的范围内的Foo。
I find that JavaScript's lack of distinction makes it far less useful than Visual Basic's variant, as the risk of ambiguity is too high. Other than that, with
is still a powerful idea that can make for better readability.
我发现JavaScript的缺乏区分使得它远不如Visual Basic的变体有用,因为含糊的风险太高了。除此之外,它仍然是一个强大的想法,可以提高可读性。
#10
7
Using "with" can make your code more dry.
使用“with”可以使您的代码更加干燥。
Consider the following code:
考虑下面的代码:
var photo = document.getElementById('photo');
photo.style.position = 'absolute';
photo.style.left = '10px';
photo.style.top = '10px';
You can dry it to the following:
你可以把它擦干:
with(document.getElementById('photo').style) {
position = 'absolute';
left = '10px';
top = '10px';
}
I guess it depends whether you have a preference for legibility or expressiveness.
我想这取决于你对易读性和表达性的偏好。
The first example is more legible and probably recommended for most code. But most code is pretty tame anyway. The second one is a bit more obscure but uses the expressive nature of the language to cut down on code size and superfluous variables.
第一个示例更清晰,可能推荐大多数代码。但是大多数代码还是很驯服的。第二种方法稍微有些晦涩,但是它使用了语言的表达性来减少代码的大小和多余的变量。
I imagine people who like Java or C# would choose the first way (object.member) and those who prefer Ruby or Python would choose the latter.
我想,喜欢Java或c#的人会选择第一种方式(object.member),而喜欢Ruby或Python的人会选择后者。
#11
7
You can use with
to introduce the contents of an object as local variables to a block, like it's being done with this small template engine.
您可以将对象的内容作为局部变量引入到块中,就像使用这个小模板引擎一样。
#12
5
I think the obvious use is as a shortcut. If you're e.g. initializing an object you simply save typing a lot of "ObjectName." Kind of like lisp's "with-slots" which lets you write
我认为最明显的用法是作为捷径。如果您正在初始化一个对象,那么您只需保存大量的“ObjectName”。有点像lisp的“带槽”,可以让你写。
(with-slots (foo bar) objectname
"some code that accesses foo and bar"
which is the same as writing
这和写作是一样的吗?
"some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""
It's more obvious why this is a shortcut then when your language allows "Objectname.foo" but still.
更明显的是,当您的语言允许“Objectname”时,这是一个快捷方式。foo”但仍然。
#13
5
Having experience with Delphi, I would say that using with should be a last-resort size optimization, possibly performed by some kind of javascript minimizer algorithm with access to static code analysis to verify its safety.
有了Delphi的经验,我想说,使用应该是最后的规模优化,可能是通过某种javascript最小化算法来实现静态代码分析,以验证其安全性。
The scoping problems you can get into with liberal use of the with statement can be a royal pain in the a** and I wouldn't want anyone to experience a debugging session to figure out what the he.. is going on in your code, only to find out that it captured an object member or the wrong local variable, instead of your global or outer scope variable which you intended.
你可以*使用的范围内的问题可以是一个**的皇家痛苦,我不想让任何人经历一个调试过程来弄清楚他到底是什么。在您的代码中,只发现它捕获了一个对象成员或错误的局部变量,而不是您想要的全局变量或外部范围变量。
The VB with statement is better, in that it needs the dots to disambiguate the scoping, but the Delphi with statement is a loaded gun with a hairtrigger, and it looks to me as though the javascript one is similar enough to warrant the same warning.
带有语句的VB更好,因为它需要点来消除scoping的歧义,但是带有语句的Delphi是带有一个发夹的上膛的枪,它在我看来就好像javascript一样,足以发出同样的警告。
#14
4
The with statement can be used to decrease the code size or for private class members, example:
可以使用with语句来减少代码大小或为私有类成员,例如:
// demo class framework
var Class= function(name, o) {
var c=function(){};
if( o.hasOwnProperty("constructor") ) {
c= o.constructor;
}
delete o["constructor"];
delete o["prototype"];
c.prototype= {};
for( var k in o ) c.prototype[k]= o[k];
c.scope= Class.scope;
c.scope.Class= c;
c.Name= name;
return c;
}
Class.newScope= function() {
Class.scope= {};
Class.scope.Scope= Class.scope;
return Class.scope;
}
// create a new class
with( Class.newScope() ) {
window.Foo= Class("Foo",{
test: function() {
alert( Class.Name );
}
});
}
(new Foo()).test();
The with-statement is very usefull if you want to modify the scope, what is necessary for having your own global scope that you can manipulate at runtime. You can put constants on it or certain helper functions often used like e.g. "toUpper", "toLower" or "isNumber", "clipNumber" aso..
如果您想要修改范围,那么with-statement非常有用,您可以在运行时操作自己的全局范围。你可以在它上面加上常数或者某些辅助函数,比如。“toUpper”,“toLower”或“isNumber”,“clipNumber”
About the bad performance I read that often: Scoping a function won't have any impact on the performance, in fact in my FF a scoped function runs faster then an unscoped:
关于糟糕的性能,我经常读到这样的情况:对函数的定义不会对性能产生任何影响,事实上,在我的FF中,作用域的函数运行得更快,然后是一个未作用域:
var o={x: 5},r, fnRAW= function(a,b){ return a*b; }, fnScoped, s, e, i;
with( o ) {
fnScoped= function(a,b){ return a*b; };
}
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnRAW(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
s= Date.now();
r= 0;
for( i=0; i < 1000000; i++ ) {
r+= fnScoped(i,i);
}
e= Date.now();
console.log( (e-s)+"ms" );
So in the above mentioned way used the with-statement has no negative effect on performance, but a good one as it deceases the code size, what impacts the memory usage on mobile devices.
因此,在上述方法中使用with-statement对性能没有任何负面影响,但是很好,因为它欺骗了代码的大小,影响了移动设备上的内存使用。
#15
4
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
不推荐使用,在ECMAScript 5严格模式中禁用。推荐的替代方法是指定要访问临时变量的属性的对象。
来源:Mozilla.org
#16
2
Using with also makes your code slower in many implementation, as everything now gets wrapped in an extra scope for lookup. There's no legitimate reason for using with in JavaScript.
使用它还会使您的代码在许多实现中变得更慢,因为现在所有东西都被打包在一个额外的查找范围内。使用JavaScript没有合理的理由。
#17
2
I think that the usefulness of with
can be dependent on how well your code is written. For example, if you're writing code that appears like this:
我认为使用的有用性取决于你的代码写得有多好。例如,如果您编写的代码是这样的:
var sHeader = object.data.header.toString();
var sContent = object.data.content.toString();
var sFooter = object.data.footer.toString();
then you could argue that with
will improve the readability of the code by doing this:
然后你可以争辩说通过这样做可以提高代码的可读性:
var sHeader = null, sContent = null, sFooter = null;
with(object.data) {
sHeader = header.toString();
sContent = content.toString();
sFooter = content.toString();
}
Conversely, it could be argued that you're violating the Law of Demeter, but, then again, maybe not. I digress =).
相反地,你可能会认为你违反了德墨忒尔定律,但是,也许不是。我跑题了=)。
Above all else, know that Douglas Crockford recommends not using with
. I urge you to check out his blog post regarding with
and its alternatives here.
最重要的是,要知道道格拉斯·克罗克福德建议不要使用。我强烈建议你去看看他的博客文章,看看有没有其他的选择。
#18
2
I think the with-statement can come in handy when converting a template language into JavaScript. For example JST in base2, but I've seen it more often.
我认为,当将模板语言转换为JavaScript时,with_statement会很有用。例如在base2中的JST,但是我经常看到它。
I agree one can program this without the with-statement. But because it doesn't give any problems it is a legitimate use.
我同意一个人可以在没有附带声明的情况下编程。但是因为它没有给任何问题,它是合法的使用。
#19
2
I think the object literal use is interesting, like a drop-in replacement for using a closure
我认为对象的字面用法很有趣,就像使用闭包的drop-in替换。
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
(function(info)
{
nodes[i].onclick = function(){ showStuff(info) };
})(data[i]);
}
or the with statement equivilent of a closure
或者是带有闭包的语句。
for(var i = nodes.length; i--;)
{
// info is namespaced in a closure the click handler can access!
with({info: data[i]})
{
nodes[i].onclick = function(){ showStuff(info) };
}
}
I think the real risk is accidently minipulating variables that are not part of the with statement, which is why I like the object literal being passed into with, you can see exactly what it will be in the added context in the code.
我认为真正的风险是意外的缩小了的变量,而不是带有语句的部分,这就是为什么我喜欢将对象文字传递进来的原因,你可以看到在代码中添加的上下文中的具体内容。
#20
2
I created a "merge" function which eliminates some of this ambiguity with the with
statement:
我创建了一个“合并”函数,它消除了一些模棱两可的语句:
if (typeof Object.merge !== 'function') {
Object.merge = function (o1, o2) { // Function to merge all of the properties from one object into another
for(var i in o2) { o1[i] = o2[i]; }
return o1;
};
}
I can use it similarly to with
, but I can know it won't affect any scope which I don't intend for it to affect.
我可以使用它,但我知道它不会影响任何我不打算影响的范围。
Usage:
用法:
var eDiv = document.createElement("div");
var eHeader = Object.merge(eDiv.cloneNode(false), {className: "header", onclick: function(){ alert("Click!"); }});
function NewObj() {
Object.merge(this, {size: 4096, initDate: new Date()});
}
#21
2
For some short code pieces, I would like to use the trigonometric functions like sin
, cos
etc. in degree mode instead of in radiant mode. For this purpose, I use an AngularDegree
object:
对于一些短小的代码片段,我想要使用诸如sin, cos等的三角函数,而不是在辐射模式下。为此,我使用了AngularDegreeobject:
AngularDegree = new function() {
this.CONV = Math.PI / 180;
this.sin = function(x) { return Math.sin( x * this.CONV ) };
this.cos = function(x) { return Math.cos( x * this.CONV ) };
this.tan = function(x) { return Math.tan( x * this.CONV ) };
this.asin = function(x) { return Math.asin( x ) / this.CONV };
this.acos = function(x) { return Math.acos( x ) / this.CONV };
this.atan = function(x) { return Math.atan( x ) / this.CONV };
this.atan2 = function(x,y) { return Math.atan2(x,y) / this.CONV };
};
Then I can use the trigonometric functions in degree mode without further language noise in a with
block:
然后,我可以在没有进一步语言噪声的情况下,在学位模式下使用三角函数:
function getAzimut(pol,pos) {
...
var d = pos.lon - pol.lon;
with(AngularDegree) {
var z = atan2( sin(d), cos(pol.lat)*tan(pos.lat) - sin(pol.lat)*cos(d) );
return z;
}
}
This means: I use an object as a collection of functions, which I enable in a limited code region for direct access. I find this useful.
这意味着:我使用一个对象作为函数的集合,我在一个有限的代码区域中允许直接访问。我觉得这很有用。
#22
1
I just really don't see how using the with is any more readable than just typing object.member. I don't think it's any less readable, but I don't think it's any more readable either.
我真的不知道如何使用它比只输入object.member更可读。我不认为它没有什么可读性,但我认为它也没有任何可读性。
Like lassevk said, I can definitely see how using with would be more error prone than just using the very explicit "object.member" syntax.
就像lassevk说的那样,我可以肯定地看到,与使用非常明确的“对象”相比,如何使用更容易出错。成员”语法。
#23
1
It's good for putting code that runs in a relatively complicated environment into a container: I use it to make a local binding for "window" and such to run code meant for a web browser.
将在相对复杂的环境中运行的代码放入容器中是很有好处的:我用它来为“窗口”做一个本地绑定,以及为web浏览器运行代码。
#24
1
You got to see the validation of a form in javascript at W3schools http://www.w3schools.com/js/js_form_validation.asp where the object form is "scanned" through to find an input with name 'email'
你可以在W3schools网站http://www.w3schools.com/js/js_form_valid. asp中看到一种表单的验证,该表单的对象表单被“扫描”,以找到一个名为“email”的输入
But i've modified it to get from ANY form all the fields validate as not empty, regardless of the name or quantity of field in a form. Well i've tested only text-fields.
但是我已经修改了它从任何形式的所有字段都验证为不空,而不考虑表单中字段的名称或数量。我只测试了文本字段。
But the with() made things simpler. Here's the code:
但是with()使事情变得更简单。这是代码:
function validate_required(field)
{
with (field)
{
if (value==null||value=="")
{
alert('All fields are mandtory');return false;
}
else
{
return true;
}
}
}
function validate_form(thisform)
{
with (thisform)
{
for(fiie in elements){
if (validate_required(elements[fiie])==false){
elements[fiie].focus();
elements[fiie].style.border='1px solid red';
return false;
} else {elements[fiie].style.border='1px solid #7F9DB9';}
}
}
return false;
}
#25
1
CoffeeScript's Coco fork has a with
keyword, but it simply sets this
(also writable as @
in CoffeeScript/Coco) to the target object within the block. This removes ambiguity and achieves ES5 strict mode compliance:
CoffeeScript的Coco fork有一个with关键字,但它只是将这个(也可写为@ in CoffeeScript/Coco)设置为block中的目标对象。这消除了歧义并实现了ES5严格的模式遵从性:
with long.object.reference
@a = 'foo'
bar = @b
#26
0
Here's a good use for with
: adding new elements to an Object Literal, based on values stored in that Object. Here's an example that I just used today:
这里有一个很好的用法:根据存储在对象中的值,将新元素添加到对象文本中。这是我今天使用的一个例子:
I had a set of possible tiles (with openings facing top, bottom, left, or right) that could be used, and I wanted a quick way of adding a list of tiles which would be always placed and locked at the start of the game. I didn't want to keep typing types.tbr
for each type in the list, so I just used with
.
我有一组可以使用的可能的瓦片(开口朝上、下、左或右),我想要一种快速的方法来添加一个方块列表,它总是在游戏开始时被放置和锁定。我不想继续打字。列表中的每一种类型的tbr,所以我只使用了。
Tile.types = (function(t,l,b,r) {
function j(a) { return a.join(' '); }
// all possible types
var types = {
br: j( [b,r]),
lbr: j([l,b,r]),
lb: j([l,b] ),
tbr: j([t,b,r]),
tbl: j([t,b,l]),
tlr: j([t,l,r]),
tr: j([t,r] ),
tl: j([t,l] ),
locked: []
};
// store starting (base/locked) tiles in types.locked
with( types ) { locked = [
br, lbr, lbr, lb,
tbr, tbr, lbr, tbl,
tbr, tlr, tbl, tbl,
tr, tlr, tlr, tl
] }
return types;
})("top","left","bottom","right");
#27
0
You can use with to avoid having to explicitly manage arity when using require.js:
在使用requires .js时,您可以使用它来避免显式地管理特性。
var modules = requirejs.declare([{
'App' : 'app/app'
}]);
require(modules.paths(), function() { with (modules.resolve(arguments)) {
App.run();
}});
Implementation of requirejs.declare:
requirejs.declare实现:
requirejs.declare = function(dependencyPairs) {
var pair;
var dependencyKeys = [];
var dependencyValues = [];
for (var i=0, n=dependencyPairs.length; i<n; i++) {
pair = dependencyPairs[i];
for (var key in dependencyPairs[i]) {
dependencyKeys.push(key);
dependencyValues.push(pair[key]);
break;
}
};
return {
paths : function() {
return dependencyValues;
},
resolve : function(args) {
var modules = {};
for (var i=0, n=args.length; i<n; i++) {
modules[dependencyKeys[i]] = args[i];
}
return modules;
}
}
}
#28
0
As Andy E pointed out in the comments of Shog9's answer, this potentially-unexpected behavior occurs when using with
with an object literal:
正如Andy E在Shog9的回答中指出的那样,这种潜在的意想不到的行为发生在使用对象文字时:
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with ({num: i}) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "[object Object]"
}
}
Not that unexpected behavior wasn't already a hallmark of with
.
并不是说这种意外的行为已经成为了我们的标志。
If you really still want to use this technique, at least use an object with a null prototype.
如果您仍然想使用这种技术,那么至少要使用一个具有空原型的对象。
function scope(o) {
var ret = Object.create(null);
if (typeof o !== 'object') return ret;
Object.keys(o).forEach(function (key) {
ret[key] = o[key];
});
return ret;
}
for (var i = 0; i < 3; i++) {
function toString() {
return 'a';
}
with (scope({num: i})) {
setTimeout(function() { console.log(num); }, 10);
console.log(toString()); // prints "a"
}
}
But this will only work in ES5+. Also don't use with
.
但这只适用于ES5+。也不要使用。
#29
0
I am working on a project that will allow users to upload code in order to modify the behavior of parts of the application. In this scenario, I have been using a with
clause to keep their code from modifying anything outside of the scope that I want them to mess around with. The (simplified) portion of code I use to do this is:
我正在做一个项目,允许用户上传代码,以修改应用程序的部分行为。在这个场景中,我使用了一个with子句来防止他们的代码修改超出我想要他们处理的范围之外的任何东西。我所使用的(简化的)代码部分是:
// this code is only executed once
var localScope = {
build: undefined,
// this is where all of the values I want to hide go; the list is rather long
window: undefined,
console: undefined,
...
};
with(localScope) {
build = function(userCode) {
eval('var builtFunction = function(options) {' + userCode + '}');
return builtFunction;
}
}
var build = localScope.build;
delete localScope.build;
// this is how I use the build method
var userCode = 'return "Hello, World!";';
var userFunction = build(userCode);
This code ensures (somewhat) that the user-defined code neither has access to any globally-scoped objects such as window
nor to any of my local variables through a closure.
该代码确保(某种程度上)用户定义的代码不能通过闭包访问任何全局范围的对象,例如窗口或任何本地变量。
Just as a word to the wise, I still have to perform static code checks on the user-submitted code to ensure they aren't using other sneaky manners to access global scope. For instance, the following user-defined code grabs direct access to window
:
对于明智的人来说,我仍然需要对用户提交的代码进行静态代码检查,以确保他们不会使用其他的鬼把戏来访问全局范围。例如,以下用户定义的代码可以直接访问窗口:
test = function() {
return this.window
};
return test();
#30
0
My
我的
switch(e.type) {
case gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED: blah
case gapi.drive.realtime.ErrorType.CLIENT_ERROR: blah
case gapi.drive.realtime.ErrorType.NOT_FOUND: blah
}
boils down to
可以归结为
with(gapi.drive.realtime.ErrorType) {switch(e.type) {
case TOKEN_REFRESH_REQUIRED: blah
case CLIENT_ERROR: blah
case NOT_FOUND: blah
}}
Can you trust so low-quality code? No, we see that it was made absolutely unreadable. This example undeniably proves that there is no need for with-statement, if I am taking readability right ;)
你能相信如此低质量的代码吗?不,我们看到它是绝对不可读的。这个例子不可否认地证明了,如果我是正确的,就不需要用with-statement。