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

For an object to implement an iterative interface, it must implement a key [Symbol.iterator]that points to a function that returns iterator. I am wondering if the loop for..ofinternally calls this method on an object to get this iterator?

The reason I'm curious is that, for example, it Mapdefines an interface with several iterators (records, values, keys), and it seems that if not specified explicitly, the loop for..ofuses an iterator, the return map.entries()call.

I am trying to find in the specification , but only indicates what iteratoris passed as a parameter to the abstract operation ForOf:

The abstract ForIn / OfBodyEvaluation operation is called with arguments lhs, stmt, iterator , iterationKind, lhsKind, and labelSet.

So basically two questions:

  • How does an iterator get from an object?
  • Where is it listed in the specification?
+4
source share
2 answers

The specific location where the action is indicated is located in 7.4.1 GetIterator (obj [, method]) . This gets the property of the @@iteratortransferred object in step 1a. abstract operation:

and. Set the GetMethod method (obj, @@ iterator).

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

for-in for-of - 13.7.5.11 :

IterationStatement: for (ForDeclaration of AssignmentExpression) Statement

, ForIn/OfBodyEvaluation - keyResult ForIn/OfHeadEvaluation. 7b:

. GetIterator (exprValue).

, for-of loop , @@iterator Symbol.iterator .

+1

Symbol.iterator, . , (entries, keys, values), , , , . , . , for..of. , [Symbol.iterator].

  • ?

, Symbol.iterator, .

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

for..of.

  1. ?

:

@@iterator "Symbol.iterator"

, Iterator . for-of.

( ) , :

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; }
+1

Source: https://habr.com/ru/post/1687225/


All Articles