Ist das Lesen der `length'-Eigenschaft eines Arrays wirklich eine so teure Operation in JavaScript?



3 Answers

TL; DR:

Von dem, was ich sammeln kann, scheint es , dass die Länge des Arrays intern (zumindest in V8) zwischengespeichert wird.

(Details? Lesen Sie weiter :))

Also, diese Frage hat sich einige Male in meinem Kopf herumgesprochen und ich habe mich entschieden, an die Wurzel des Problems zu kommen (zumindest in einer Implementierung).

Um V8-Quelle zu JSArray ergab die JSArray Klasse.

// The JSArray describes JavaScript Arrays
//  Such an array can be in one of two modes:
//    - fast, backing storage is a FixedArray and length <= elements.length();
//       Please note: push and pop can be used to grow and shrink the array.
//    - slow, backing storage is a HashTable with numbers as keys.

Ich nehme an, dass die Art der Array-Elemente vorgibt, ob sie schnell oder langsam ist. Ich setzte mich auf ein Bit-Flag, das in set_has_fast_elements ( set_bit_field2(bit_field2() | (1 << kHasFastElements)) ), wo ich dachte, ich würde die Grabungslinie zeichnen, wie ich in Google-Code sah und nicht habe die Quelle lokal.

Nun scheint es , dass jedes Mal, wenn eine Operation für das Array ausgeführt wird (was eine JSObject Klasse von JSObject , ein Aufruf an NormalizeElements() , der Folgendes ausführt:

// Compute the effective length.
  int length = IsJSArray() ?
      Smi::cast(JSArray::cast(this)->length())->value() :
      array->length();

Also, bei der Beantwortung Ihrer Fragen:

  1. In Chrome (oder anderen Browsern, die V8 verwenden) scheint es keinen Vorteil zu geben, die length -Eigenschaft eines Arrays zwischenzuspeichern (es sei denn, du machst etwas Seltsames, das es slow (ich bin mir nicht sicher, was diese sind) Bedingungen sind) - nachdem ich das gesagt habe, werde ich wahrscheinlich die Cache- length bis ich die Möglichkeit habe, alle Betriebssystem-Browser-Implementierungen zu durchlaufen;)
  2. Die length -Eigenschaft scheint nach jeder Operation auf dem Objekt geändert zu werden.

Bearbeiten:

Nebenbei bemerkt scheint es, dass ein "leeres" Array tatsächlich 4 Elementen zugeordnet ist:

// Number of element slots to pre-allocate for an empty array.
static const int kPreallocatedArrayElements = 4;

Ich bin nicht sicher, wie viele Elemente das Array erweitert, sobald die Grenzen überschritten wurden - ich habe nicht so tief graben :)

javascript arrays

Ich habe immer angenommen, dass das Caching der Länge eines Arrays in JavaScript eine gute Idee ist (besonders im Zustand einer for Schleife), weil es teuer ist, die Länge eines Arrays zu berechnen.

Beispiel

for (var i = 0; i < arr.length; i++) { }

// vs

for (var i = 0, arrLength = arr.length; i < arrLength; i++) { }

Ich dachte jedoch, dass die length -Eigenschaft nur bei der Erstellung und Änderung des Arrays aktualisiert wird. Deshalb sollte das Lesen nicht zu teuer sein, statt es in einer Variablen zu lesen (im Gegensatz zu anderen Methoden in anderen Sprachen, die im Speicher suchen müssen, um das Ende von etwas zu finden, zB strlen() in C ).

Ich habe zwei Fragen. Ich bin auch daran interessiert, wie das funktioniert, also treffe mich bitte nicht mit dem vorzeitigen Optimierungs- Stick.

Übernehmen Sie die JavaScript-Engines in Browsern.

  1. Hat es einen Vorteil, die Eigenschaft length eines Arrays in JavaScript zwischenzuspeichern? Ist beim Lesen einer lokalen Variablen über die Eigenschaft eines Objekts viel mehr beteiligt?
  2. Wird die length -Eigenschaft einfach bei der Erstellung und bei den Methoden shift() und pop() geändert, die kein neues Array zurückgeben und ansonsten einfach als Integer gespeichert werden?



Nur eine Notiz:

Bei einigen Browsern (ich habe es in Safari, IE und Opera bemerkt), können Sie eine Geschwindigkeitssteigerung erzielen, indem Sie die Länge innerhalb der for-Schleifen-Deklaration zwischenspeichern:

var j;
for (var i = 0, len = arr.length; i < len; i++) {
  j = arr[i];
}

Ich habe @ KooiIncs Jsperf-Test oben bearbeitet, um diesen Fall hinzuzufügen .




Achten Sie darauf, dass dies nicht für alle iterierbaren Sammlungen gilt. Beispielsweise ist die Zwischenspeicherung der Länge einer HTMLCollection in Chrome (Version 41) 65% schneller und in Firefox (Version 36) um 35% schneller.

http://jsperf.com/array-length-in-loop-dom




Related