Are there legitimate uses for JavaScript's “with” statement?

后端 未结 30 1795
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 04:22

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 ne

相关标签:
30条回答
  • 2020-11-22 05:23

    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.

    0 讨论(0)
  • 2020-11-22 05:23

    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:

    // 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();
    
    0 讨论(0)
  • 2020-11-22 05:25

    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.

    0 讨论(0)
  • 2020-11-22 05:25

    As Andy E pointed out in the comments of Shog9's answer, this potentially-unexpected behavior occurs when using with with an object literal:

    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.

    0 讨论(0)
  • 2020-11-22 05:26

    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.

    Source: Mozilla.org

    0 讨论(0)
  • 2020-11-22 05:27

    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.

    I agree one can program this without the with-statement. But because it doesn't give any problems it is a legitimate use.

    0 讨论(0)
提交回复
热议问题