什么取代“与”?

时间:2011-08-17 15:28:37

标签: javascript

我知道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做得很好的事情。

我是否至少从严格模式中获取块范围?

6 个答案:

答案 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

要拿走两件事:

  • 严格模式是ECMA5中唯一禁止的地方
  • 建议的替代方案是您的选择(c)

正如你所说,它不是“有意义”的唯一原因是选择像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。