2014-07-22 7 views
6

Ich habe mich nur gefragt, ob es einen Weg gibt, eine Objekteigenschaft enumerable wie in einem for in Schleife aber nicht zeigen, bis in einer for of loop Art wieKönnen Sie Eigenschaften in JavaScript aufzählbar, aber nicht iterierbar machen?

Object.defineProperty({},'prop',{ 
    enumerable:true, 
    iterable:false 
} 

wenn nicht, gibt es Pläne, eine Funktion zu implementieren zu machen so was? Oder verwendet die for of Schleife die aufzählbare Eigenschaft

+0

ich es gegoogelt haben ... I habe nichts gefunden, was darauf hindeutet, dass es ein Attribut mit genau diesem Namen geben wird. Ich frage mich nur, ob sie irgendwelche Pläne haben, einen Weg zu implementieren, um Werte iteratable und Schlüssel nicht enumberable zu machen, ich werde meine Frage aktualisieren, um das ein wenig klarer –

+1

dann zu machen, fragst du wahrscheinlich an der falschen Stelle. Auf den ES6-Mailinglisten zu antworten ist viel wahrscheinlicher, um Ihnen Antwort zu geben, die Sie wünschen. Stackoverflow geht in erster Linie darum, Code-Fragen mit Code-Antworten zu stellen. –

+4

@ Mike'Pomax'Kamermans Kein Grund, unhöflich zu sein. Abgesehen von der Einstellung gibt es an dieser Frage nichts Außergewöhnliches. Wir haben viele ähnliche Fragen gesehen, als C++ 11 gegründet wurde. –

Antwort

4

Ich habe etwas im Mozilla Development Network (MDN) herum gegraben.

Stellt fest, dass Objekte über eine obj.propertyIsEnumerable(prop)-Methode verfügen, um zu überprüfen, ob die Eigenschaft aufzählbar ist. Aus den in MDN angegebenen Beispielen sind die über die Prototypkette geerbten Eigenschaften nicht aufzählbar, daher gibt die Methode für diese Eigenschaften false zurück.

Ein Beispiel für nicht aufzählbare Eigenschaften sind Konstruktoren und die Eigenschaft length von Arrays.

Für den iterablen Teil der Frage, zitieren MDN: "Iterable in ECMAScript 6 ist eine Schnittstelle (oder mit anderen Worten, ein Protokoll), nicht eine Art von Objekt wie Array oder Map".

Das heißt, das Objekt muss diese Schnittstelle implementieren, um seine Eigenschaften iterierbar zu machen. Dies ist der Fall für integrierte Iterables wie String-, Array-, Map-, Set-, WeakSet- und Generator-Objekte.

Der folgende Code veranschaulicht dies:

var aString = "hello" 
typeof aString[Symbol.iterator] // "function" 
aString[Symbol.iterator]() + "" // "[object String Iterator]" 
[...aString]     // ["h", "e", "l", "l", "o"] 

Natürlich können Sie Ihre eigenen Iterator Implementierung definieren.

Zurückkommend auf die Frage, Eigenschaften an das Objekt oder seinen Prototyp (direkt, dh nicht über Vererbung) wird als Enumerable in der for...in Schleife angezeigt. Für die Iterables benötigen Sie eine Implementierung, entweder die zuvor erwähnten oder Ihre eigenen. Hier ist ein großartiges Beispiel von MDN.

let arr = [ 3, 5, 7 ]; 
arr.foo = "hello"; 

for (let i in arr) { 
    console.log(i); // logs "0", "1", "2", "foo" these are property names or indexes 
} 

for (let i of arr) { 
    console.log(i); // logs "3", "5", "7" these are actual values of an 
        // iterable implementation provided by the array prototype 
} 

let Das Schlüsselwort entspricht in diesem Zusammenhang auf eine var Definition (obwohl es mehr Auswirkungen hat, sondern sie sind außerhalb des Umfangs dieser Veröffentlichung).

Wie Sie das Array sehen können eine Implementierung bereits die iterable Schnittstelle hat (aus dem Array Prototyp), so ergibt es seine Werte, wenn die for...of-Schleife, während die foo Eigenschaft nicht angezeigt wird (weder Wert noch Eigenschaftsname) .

Wenn also Ihr Objekt keine iterable-Schnittstelle implementiert, sollte es (im Prinzip) nicht iterierbar sein und wird daher seine Eigenschaften in einer for...of-Schleife anzeigen.

2

Der Unterschied zwischen for in and for of evaluations ist, dass man obj.[[enumerate]] verwendet und der andere GetIterator(obj) verwendet, um die geloopten Elemente zu bestimmen. [[enumerate]] does (es sei denn obj ist ein Proxy)

Liefert ein Iterator object deren next Verfahren iteriert über alle String-wertige Schlüssel enumerable Eigenschaften von obj.

GetIterator wird (versuchen) rufen die @@iterate method - jedoch normale Objekte haben diese Schnittstelle nicht implementieren.

So wird kein Eigentum in for of Schleifen auftauchen, wenn Sie es explizit angeben:

function defineIterableProperty(obj, prop, desc) { 
    let old = obj[Symbol.iterate]; 
    Object.defineProperty(obj, prop, desc); 
    obj[Symbol.iterate] = function*() { 
     if (old) yield* old.call(this); 
     yield prop; 
    }; 
    return obj; 
} 

(ungetestet, aber ich hoffe, Sie bekommen die Idee)