How does `for..of` loop resolve the iterator from an object?

后端 未结 2 1103
太阳男子
太阳男子 2021-01-19 17:35

For an object to implement iterable interface it must implement [Symbol.iterator] key that points to a function that returns the iterator. I\'m won

相关标签:
2条回答
  • 2021-01-19 18:21

    The specific place where the operation is specified is in 7.4.1 GetIterator( obj [ , method ] ). This gets the @@iterator property of the passed object in step 1a. of the abstract operation:

    a. Set method to GetMethod(obj, @@iterator).

    @@iterator is a well-known symbol that is the Symbol.iterator property on objects.

    This is used by for-in and for-of loops due to the productions in 13.7.5.11 Runtime Semantics:

    IterationStatement : for(ForDeclaration of AssignmentExpression) Statement

    1. Let keyResult be the result of performing ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, iterate).
    2. Return ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexicalBinding, labelSet).

    Here, you can see the iterator argument passed to ForIn/OfBodyEvaluation is the return value keyResult of ForIn/OfHeadEvaluation. The return value is, in step 7b:

    b. Return GetIterator(exprValue).

    Thus, for-of loops get the iterator by accessing the @@iterator or Symbol.iterator well-known symbol by specification.

    0 讨论(0)
  • 2021-01-19 18:23

    An object can define only one symbol Symbol.iterator, which is the one that will be called on iteration on the object itself. The other properties of the object, such as the examples you have given (entries, keys, values) may also return an iterator, but those are in general not the same iterators. They could be the same, but that is just an implementation choice. There is no ambiguity as to which iterator is called when iterating the object with for..of. It is the one returned by [Symbol.iterator].

    1. How iterator is obtained from an object?

    You can get it by calling the function keyed with Symbol.iterator, e.g.

    const iterator = obj[Symbol.iterator]();
    

    It is retrieved implicitly with for..of.

    1. Where is it specified in the spec?

    This table in the specs explains:

    @@iterator "Symbol.iterator"

    A method that returns the default Iterator for an object. Called by the semantics of the for-of statement.

    Here is how you can make a custom function for returning the default iterator for an object (overwriting the default one), and see how it gets called:

    const obj = {
        // Define a custom function for returning the default iterator for this object
        [Symbol.iterator]: function () {
            console.log('The iterator-returning function got invoked');
            // Return an iterator from some other object
            //  (but we could have created one from scratch as well):
            return 'abc'[Symbol.iterator]();
        },
        myMethod: function () {
            // This method happens to return the same iterator
            return this[Symbol.iterator]();
        },
        myOtherMethod: function () {
            // This method happens to return another iterator
            return 'def'[Symbol.iterator]();
        }
    }
    
    for (const a of obj) {
        console.log(a); // a b c
    }
    for (const a of obj.myMethod()) {
        console.log(a); // a b c
    }
    for (const a of obj.myOtherMethod()) {
        console.log(a); // d e f
    }
    .as-console-wrapper { max-height: 100% !important; top: 0; }

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