Alan Storm对我关于with声明的回答的评论引起了我的思考。我很少找到使用这个特殊语言特性的理由,也从来没有想过它可能会带来什么麻烦。现在,我很好奇如何有效地利用with,同时避免它的陷阱。
你觉得with语句在哪里有用?
Alan Storm对我关于with声明的回答的评论引起了我的思考。我很少找到使用这个特殊语言特性的理由,也从来没有想过它可能会带来什么麻烦。现在,我很好奇如何有效地利用with,同时避免它的陷阱。
你觉得with语句在哪里有用?
当前回答
是的,是的,是的。有一个非常合理的用法。看:
with (document.getElementById("blah").style) {
background = "black";
color = "blue";
border = "1px solid green";
}
基本上任何其他DOM或CSS钩子都是with的奇妙用途。这并不是说“CloneNode”将是未定义的,并返回到全局作用域,除非你走出你的方式,决定让它成为可能。
Crockford对速度的抱怨是with创建了一个新的上下文。上下文通常是昂贵的。我同意。但如果你只是创建了一个div,没有一些框架来设置你的css,需要手动设置15个左右的css属性,那么创建一个上下文可能会比创建变量和15个解引用更便宜:
var element = document.createElement("div"),
elementStyle = element.style;
elementStyle.fontWeight = "bold";
elementStyle.fontSize = "1.5em";
elementStyle.color = "#55d";
elementStyle.marginLeft = "2px";
等等……
其他回答
我只是不明白使用with比直接输入object。member有什么更好读的地方。我不认为它的可读性有任何下降,但我也不认为它的可读性有任何提高。
就像lassevk说的,我可以肯定地看到使用with比使用非常显式的“object”更容易出错。成员”语法。
它很适合将在相对复杂的环境中运行的代码放入容器中:我使用它来为“窗口”创建本地绑定,从而运行用于web浏览器的代码。
你可以定义一个小的帮助函数来提供with的好处,而不会产生歧义:
var with_ = function (obj, func) { func (obj); };
with_ (object_name_here, function (_)
{
_.a = "foo";
_.b = "bar";
});
只是想添加你可以得到“with()”功能与漂亮的语法和没有歧义与你自己的聪明的方法…
//utility function
function _with(context){
var ctx=context;
this.set=function(obj){
for(x in obj){
//should add hasOwnProperty(x) here
ctx[x]=obj[x];
}
}
return this.set;
}
//how calling it would look in code...
_with(Hemisphere.Continent.Nation.Language.Dialect.Alphabet)({
a:"letter a",
b:"letter b",
c:"letter c",
d:"letter a",
e:"letter b",
f:"letter c",
// continue through whole alphabet...
});//look how readable I am!!!!
..或者,如果你真的想使用"with()"而不带歧义和自定义方法,可以将它包装在匿名函数中并使用.call
//imagine a deeply nested object
//Hemisphere.Continent.Nation.Language.Dialect.Alphabet
(function(){
with(Hemisphere.Continent.Nation.Language.Dialect.Alphabet){
this.a="letter a";
this.b="letter b";
this.c="letter c";
this.d="letter a";
this.e="letter b";
this.f="letter c";
// continue through whole alphabet...
}
}).call(Hemisphere.Continent.Nation.Language.Dialect.Alphabet)
然而,正如其他人所指出的,这有点毫无意义,因为你可以做……
//imagine a deeply nested object Hemisphere.Continent.Nation.Language.Dialect.Alphabet
var ltr=Hemisphere.Continent.Nation.Language.Dialect.Alphabet
ltr.a="letter a";
ltr.b="letter b";
ltr.c="letter c";
ltr.d="letter a";
ltr.e="letter b";
ltr.f="letter c";
// continue through whole alphabet...
我正在开发一个项目,该项目允许用户上传代码以修改应用程序部分的行为。在这个场景中,我一直使用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);
这段代码(一定程度上)确保用户定义的代码既不能访问任何全局作用域的对象,如window,也不能通过闭包访问任何局部变量。
简单地说,我仍然必须对用户提交的代码执行静态代码检查,以确保他们没有使用其他偷偷摸摸的方式访问全局作用域。例如,下面的用户定义代码获取对window的直接访问:
test = function() {
return this.window
};
return test();