0

The ecma262 specification has a heading with the name 13.7.5.15EnumerateObjectProperties As we can understand from its name, it is responsible for enumirating properties in objects. This "semi-algorithm" says that objects must follow the following rules (I will not list all, because the rest are obvious):

  1. The iterator's throw and return methods are null and are never invoked.

If I understand everything correctly, then the iterator should return null, and it returns undefined when trying to call these methods. Although it probably means that the iterator does not have these methods and they are empty as a fact and do not have the value of emptiness in the form of type null.

  1. Properties of the target object may be deleted during enumeration. A property that is deleted before it is processed by the iterator's next method is ignored.

Yes, the property can indeed be deleted during the enumeration (meaning for...in/of).

/// Deletion properties on object
var arr = {a:111,b:222,c:333,d:444,e:555,f:666,g:777,h:888,i:999};
for(var item in arr){
    if(item == "c") delete arr["c"];
    if(item == "e") delete arr["e"];
    if(item == "h") delete arr["h"];
    console.log(arr[item]); /// when we will be on property "c", we can delete it, it's will accomplished successfull
}
console.log(arr);

But the second sentence confuses me. It is said that a property that is deleted before the iterator process the next method will be ignored. Can you demonstrate such an example? For some reason I fell into a confusion and could not.

  1. If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration

This is true (at least in chrome):

/// Addition properties on object
var arr = {a:111,b:222,c:333,d:444,e:555,f:666,g:777,h:888,i:999};
for(var item in arr){
    if(item == "c") arr["c1"] = 1;
    if(item == "e") arr["e1"] = 1;
    if(item == "h") arr["h1"] = 1;
    console.log(arr[item]);
}
console.log(arr);
  1. EnumerateObjectProperties must obtain the own property keys of the target object by calling its [[OwnPropertyKeys]] internal method.

And in my opinion one of the important statements in this paragraph. As you understand, [[OwnPropertyKeys]] defines the order in which properties are listed in an object. Therefore, we look at the second paragraph of our header:

The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

Uhm? What? Can you explain what the hell?

MaximPro
  • 563
  • 8
  • 21
  • 2
    "It is said that a property that is deleted before the iterator process the next method will be ignored. Can you demonstrate such an example? " Try changing your `if` statement to be `if(item == "c") delete arr["e"];` – racraman Dec 18 '19 at 02:49
  • @racman it will deleted, what does't conform to specification rules. Or what will be ignored? – MaximPro Dec 18 '19 at 03:39
  • The spec says "before it is processed", but your example code deletes it _after_ it is processed. The example in @racraman's comment would delete `e` before, and demonstrate the spec behavior where `e` is not iterated. – loganfsmyth Dec 18 '19 at 03:43
  • @loganfsmyth my example was not originally made for this. By the way, what is the expected behavior result? – MaximPro Dec 18 '19 at 03:46
  • 1
    `for (var item in {a:1, b:2, c:3}) { if(item == "a") delete arr["b"]; console.log(item); }` will not log `b`. – loganfsmyth Dec 18 '19 at 03:51
  • @loganfsmyth ah, ok, I tested it before. Alright. – MaximPro Dec 18 '19 at 03:52
  • *"Uhm? What? Can you explain what the hell?"* If I remember correctly, the explanation was that while the algorithm is *getting* the properties via `[[OwnPropertyKeys]]`, it doesn't mean that it has to process or output them in the same order. – Felix Kling Dec 18 '19 at 10:14
  • Related: [Does ES6 introduce a well-defined order of enumeration for object properties?](https://stackoverflow.com/q/30076219/218196) – Felix Kling Dec 18 '19 at 10:18

1 Answers1

0

It is said that a property that is deleted before the iterator process the next method will be ignored.

This means you can delete elements during iteration that have not been reached yet and they will not be enumerated then:

const obj = { a: 1, b: 2, c: 3 };


for(let prop in obj) {
  console.log('prop', prop);
  delete obj.b;
}

This is actually different from anything you can do with a for of loop and Object.entries():

const obj = { a: 1, b: 2, c: 3 };


for(let [prop] of Object.entries(obj)) {
  console.log('prop', prop);
  delete obj.b;
}

The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

The engine has some freedom here. There are some rules to follow, but for example it seems open in what order the engine chooses to enumerate the prototype chain. That it must call [[OwnPropertyKeys]] does not mean its not allowed to resort the result before processing.

Lux
  • 17,835
  • 5
  • 43
  • 73