我知道with
应该是一个“坏部分”,但我从不关心,因为我只是小心翼翼地使用它(同上,顺便说一句,在块中有var
语句)。现在,我知道with
已经从EcmaScript 5.0严格模式中消失了。
这是我的用例:我有一个可以导出20或30个函数的库。我的大部分代码从不使用任何库,但是使用它们的部分很多。
现在,我的代码如下:
with (mylib) {
f1(f2(f1(), f3())); // five or 10 more lines like this
}
为了顺从,我将不得不......
a)将所有功能移至全局范围(yuck)。
b)mylib.f1(mylib.f2(mylib.f1(), mylib.f3()));
(这是详细的)
c)var x = mylib; x.f1(x.f2(x.f1(), x.f3()));
(稍微冗长但意义不大)。
请告诉我现在有更好的解决方案。我想要的是将对象的内容导出到范围级别的某种方式(完全 with
的用途)。
修改
我应该做的事情更清楚。我不希望别人向我解释为什么我不想做我想做的事情;我希望别人向我解释如何做我实际想做的事。
问题是,由于我无法控制的原因,库的导出都具有非常可识别的名称。不要将它们称为f1,f2等,而是将它们称为Bobs_Library_Function_F1,Bobs_Library_Function_F2等等。
我只是不想要很多看起来像
的代码Bobs_Library.Bobs_Library_Function_F1(Bobs_Library.Bobs_Library_Function_F2(Bobs_Library.Bobs_Library_Function_F1(), Bobs_Library.Bobs_Library_Function_F3()));
(实名并不是那么糟糕,实际上它们非常漂亮,并且前缀削减了。)
认真的任何人都不同意这里,好吧,我希望你在使用$.whatever
时永远不会使用jQuery.whatever
,因为这会让你看起来像个大人物伪君子。
我正在考虑使用$$.f1
...
进一步编辑
说真的,感谢所有的投入,但我不是在寻找关于(a),(b)或(c)是否最好的民意调查。我正在寻找选择(d)做with
做得很好的事情。
我是否至少从严格模式中获取块范围?
答案 0 :(得分:9)
with
很糟糕,因为在块中,你不知道变量来自哪里。 f1
等于mylib.f1
还是window.f1
?
我建议选择b)
。如果需要,您可以使用c)
,它可能对长对象名称有帮助,但b)
是可行的方法。
编辑:另一个建议是使用选项a)
,但在完成后从窗口中删除引用。另外,请注意不要覆盖window
中的任何现有属性。如果需要,您可以将它们放入另一个对象中以便保存。建立在@Alex's answer之上:
var bkupWin = {}; // Object to store existing window properties
for(var key in myLib) {
if(myLib.hasOwnProperty(key)){
if(window.hasOwnProperty(key)){
bkupWin[key] = window[key]; // Backup current property
}
window[key] = myLib[key]; // Add property to window
}
}
f1(f2(f1(), f3()));
for(var key in myLib){
if(myLib.hasOwnProperty(key)){
delete window[key]; // Remove property from window
if(bkupWin.hasOwnProperty(key)){
window[key] = bkupWin[key]; // Restore old property
}
}
}
答案 1 :(得分:4)
根据Mozilla的说法:
不推荐使用with,并且在ECMAScript 5 strict中禁止使用 模式。建议的替代方法是分配其对象 要访问临时变量的属性。 资料来源:https://developer.mozilla.org/en/JavaScript/Reference/Statements/with
要拿走两件事:
正如你所说,它不是“有意义”的唯一原因是选择像x
这样的变量 - 这是最不具描述性的事物。
mylib.f1(
mylib.f2(
mylib.f1(),
mylib.f3()
)
);
已经更具可读性,并没有比with
占用更多的空间。如果您确实想要链接方法调用,请让这些方法返回this
:
var mylib = {
f1: function () {
/* do stuff */
return this;
},
f2: function () {
/* do stuff */
return this;
}
}
// then you can chain calls, organize with indentation
mylib
.f1()
.f2();
答案 2 :(得分:3)
没有一个例子是可读的,我更喜欢这样的东西:
var
param1 = mylib.f1(),
param2 = mylib.f3(),
result = mylib.f2(param1, param2);
mylib.f1(result);
当然,变量名称应该重命名为其内容描述的内容。这会创建大量代码,但它是可读的,更重要的是它更容易调试。缩小它使用特殊程序,甚至能够以某种方式优化代码。
答案 3 :(得分:1)
如果这些都像你的例子一样应用于同一个对象,你可以编写像
这样的包装器方法function f4() {
return this.f1(this.f2(this.f1(), this.f3()));
}
并将其添加到mylib
。所以至少丑陋会包含在你的对象中。
答案 4 :(得分:1)
也许您可以为您的库创建一些外观函数,以减少选项b或c的一些噪音。所以,这......
mylib.f1(mylib.f2(mylib.f1(), mylib.f3()));
会变成......
mylib.f123_facade();
除此之外,我认为你可能只需忍受这种混乱。
答案 5 :(得分:0)
如果库不是太干扰(覆盖任何东西),您可以将整个库导出到全局范围:
for (var key in myLib) {
if (myLib.hasOwnProperty(key)) {
window[key] = myLib[key];
}
}
编辑:如果图书馆使用this
,你必须要小心。
EDIT2:您可以强制使用自己的范围并模仿with功能:
function doWith(func, myLib) {
for (var key in myLib) {
if (myLib.hasOwnProperty(key)) {
this[key] = myLib[key];
}
}
func.apply(this)
}
一个例子:
var lib = {
init: function(param1) {
console.log(param1);
},
f2: function() {
return "hi";
}
};
doWith(function(){init(f2());},lib)
在此处查看:http://jsfiddle.net/msm595/AenUc/1/
EDIT3:NVM,Rocket是正确的OTL。