Inconsistent scope rules of variables in for, for-in and for-of loops

前端 未结 4 971
日久生厌
日久生厌 2020-12-07 03:25

So I noticed that I have to use let inside a for loop, and cannot use const. However, I found that I can use const inside

4条回答
  •  孤城傲影
    2020-12-07 03:59

    So I noticed that I have to use let inside a for loop, and cannot use const.

    No. You can use a const declaration in a for loop just fine. The problem just is that const declares a constant binding, so an increment i++ doesn't work on const i (it should throw an exception, make sure you're in strict mode).

    An example of how to use const:

    for (const o = {index: 0, value: null}; o.index < arr.length; o.index++) {
        o.value = arr[o.index];
        doSomething(o);
    }
    

    Or one where it makes more sense:

    for (const iterator = makeIterator(); !iterator.isDone(); iterator.next())
        doSomething(iterator.getCurrent());
    }
    

    Intuitively I can rationalize that this is because the for loop is implemented differently/is more primitive, whereas the other constructs desugar into for loops where the iterating variable is assigned at the top of the for loop.

    Yes. In a for loop, you need to take care of updating the iteration variables yourself.

    • for ([var] init; condition; update) {
          body
      }
      becomes
      [var] init;
      while (condition) {
          body;
          update;
      }
    • for (const init; condition; update) {
          body
      }

      becomes

      {
          const init;
          while (condition) {
              body;
              update;
          }
      }
    • for (let init; condition; update) {
          body
      }

      becomes something more complicated

    In for … in and for … of loops, you just declare an assignment target expression for the produced value.

    • for ([var]/let/const target of iterable) {
          body
      }

      becomes

      {
          const _iterator = iterable[Symbol.iterator]();
          let _result;
          while (!(_result = _iterator.next()).done) {
              [var]/let/const target = _result.value;
              body;
          }
      }
    • for (… in enumerable) is just the same as for (… of Reflect.enumerate(enumerable)).

    The only thing I could find on Mozilla MDN about this was on the for loop page, which also seems wrong.

    Yes, looks like that section hasn't yet been updated for ES6.

提交回复
热议问题