2017-12-15 2 views
2

Im Voraus für lange Post entschuldigen. Ich versuche zu verstehen, Array reduzieren Polyfill von MDN zur Verfügung gestellt. Ich konnte einige Zeilen in der Polyfill nicht verstehen, kannst du es bitte erklären. Unten ist der CodeArray Reduce Polyfill Erklärung

if (!Array.prototype.reduce) { 
     Object.defineProperty(Array.prototype, 'reduce', { 
     value: function(callback /*, initialValue*/) { 
      if (this === null) { 
      throw new TypeError('Array.prototype.reduce ' + 
       'called on null or undefined'); 
      } 
      if (typeof callback !== 'function') { 
      throw new TypeError(callback + 
       ' is not a function'); 
      } 

      // 1. Let O be ? ToObject(this value). 
      var o = Object(this); 

      // 2. Let len be ? ToLength(? Get(O, "length")). 
      var len = o.length >>> 0; 

      // Steps 3, 4, 5, 6, 7  
      var k = 0; 
      var value; 

      if (arguments.length >= 2) { 
      value = arguments[1]; 
      } else { 
      while (k < len && !(k in o)) { 
       k++; 
      } 

      // 3. If len is 0 and initialValue is not present, 
      // throw a TypeError exception. 
      if (k >= len) { 
       throw new TypeError('Reduce of empty array ' + 
       'with no initial value'); 
      } 
      value = o[k++]; 
      } 

      // 8. Repeat, while k < len 
      while (k < len) { 
      // a. Let Pk be ! ToString(k). 
      // b. Let kPresent be ? HasProperty(O, Pk). 
      // c. If kPresent is true, then 
      // i. Let kValue be ? Get(O, Pk). 
      // ii. Let accumulator be ? Call(
      //   callbackfn, undefined, 
      //   « accumulator, kValue, k, O »). 
      if (k in o) { 
       value = callback(value, o[k], k, o); 
      } 

      // d. Increase k by 1.  
      k++; 
      } 

      // 9. Return accumulator. 
      return value; 
     } 
     }); 
    } 

Question1: Wenn Sie sehen, Schritt 1,

var o = Object(this); 

ich beide Werte von o und dies überprüft haben, durch ein Array an die polyfill Methode übergeben. Es gibt keinen Unterschied zwischen o und diesem. Beide sind Arrays (array.isarray hat bei beiden true zurückgegeben) mit demselben Array-Wert. Warum nicht unten statt verwenden ..?

var o = this; 

Question2: Schritt 2

var len = o.length >>> 0; 

Above Linie zu verschieben, um die o.length nach rechts scheint (32 Bit). Jedoch ist die Anzahl der verschobenen Bits gleich 0. Welchen Vorteil haben wir also, wenn wir 0 Bits verschieben? Warum nicht stattdessen unten ... verwenden?

var len = o.length; 

Frage 3: Die erste während Zustand im Inneren anders als unter

while (k < len && !(k in o)) { 
    k++; 
    } 

Zunächst k auf 0 gesetzt und es scheint immer in o zu existieren. Diese While-Loop-Bedingung wird also nie wahr. Also warum brauchen wir diese While-Schleife, wenn sie nie reinkommt?

Antwort

3

Frage 1:

Um sicherzustellen, dass reduce auf einem Objekt aufgerufen wird als genannt werden reduzieren könnte durch Function#call, Function#apply oder sogar Function#bind gebunden:

Array.prototype.reduce.call(undefined, function() {});

So beim Zugriff auf Eigenschaften wie length, ein Fehler zu sagen can't access property **** of undefined wird nicht geworfen.

HINWEIS: Das obige Beispiel verwendet das native reduce, das tatsächlich einen Fehler auslöst, wenn es nicht mit einem Objekt bereitgestellt wird.

Frage 2:

immer um einen gültigen Integer-Wert als length haben (auch wenn es nicht existiert):

console.log(5 >>> 0);   // 5 
 
console.log(5.5 >>> 0);  // 5 
 
console.log("5" >>> 0);  // 5 
 
console.log("hello" >>> 0); // 0 
 
console.log(undefined >>> 0); // 0

Frage 3:

Um mit spärlichen Arrays zu umgehen:

var arr = [5, 6]; 
 
arr[7000000] = 7; 
 

 
arr.reduce(function(acc, v, i) { 
 
    console.log("index:", i); 
 
}, 0);

Es wird nicht durch alle Indizes 0-7000000 gehen, nur diejenigen, die wirklich existieren.

+2

Re: Frage 3, Sie könnten auch 'arr = new Array (700000)' und dann 'arr [1] = someValue'. Dann wäre "0 in arr" "falsch", aber "1 in arr" wäre "wahr", also würden Sie in diesem Fall immer noch "k> 0" erhalten. –

+0

Auch re: Frage 1, die Sie anrufen können (5) .length', aber Sie können '(undefined) .length' nicht aufrufen. Ich denke, das ist aus Sicherheitsgründen getan, obwohl sie auch die Prüfung "=== Null" haben. –

+0

@ExplosionPills Das war eigentlich mein erstes Beispiel. Ich rollte zurück. BTW der Pollyfill hat die '=== Null' Prüfung. Sie sollten '==' anstelle von '===' verwenden, um auch 'undefined' einzubeziehen. –