2014-06-12 13 views
8

in questa pagina MDN [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find] c'è questa polyfill:qualcuno può spiegare questo polyray di array.prototype.find()?

if (!Array.prototype.find) { 
    Object.defineProperty(Array.prototype, 'find', { 
    enumerable: false, 
    configurable: true, 
    writable: true, 
    value: function(predicate) { 
     if (this == null) { 
     throw new TypeError('Array.prototype.find called on null or undefined'); 
     } 
     if (typeof predicate !== 'function') { 
     throw new TypeError('predicate must be a function'); 
     } 
     var list = Object(this); 
     var length = list.length >>> 0; 
     var thisArg = arguments[1]; 
     var value; 

     for (var i = 0; i < length; i++) { 
     if (i in list) { 
      value = list[i]; 
      if (predicate.call(thisArg, value, i, list)) { 
      return value; 
      } 
     } 
     } 
     return undefined; 
    } 
    }); 
} 

La mia domanda è che cosa sono queste righe per:

var list = Object(this); 
var length = list.length >>> 0; 

dal this è sicuramente una matrice (stiamo aumentando Array.prototype) quindi, perché assicurarsi che length sia numerico e perché viene utilizzato Object()?

+2

il problema con questo polyfill è che richiede la Metodo Object.defineProperty, che non è disponibile nei browser meno recenti che non implementano find. – kennebec

+0

Come risposta indicata; 'Questo non è garantito come array, puoi vedere nella seguente risposta che cosa può essere questo (se hai bisogno di più informazioni di TJ fornite): http://stackoverflow.com/a/16063711/1641941 (sotto 'questa variabile') – HMR

risposta

10

La risposta fondamentale è che il polyfill sta semplicemente implementando fedelmente i passaggi 1 e 4 dell'algoritmo nella bozza delle specifiche ES6 (§22.1.3.8 a partire dalla bozza del 22 maggio).

1. Let O essere il risultato della chiamata ToObject passare il valore di questo come argomento.

...

4. Facciamo len essere ToLength (lenValue).

(Dove ToLength è fondamentalmente una conversione in un numero.)

E come è possibile utilizzare valori non oggetto di this oggi (via Function#call e Function#apply, o semplicemente chiamata diretta in modalità rigorosa), la fase 1 ha senso.

dal this è sicuramente un array (stiamo aumentando Array.prototype) quindi perché assicurarsi che la lunghezza è numerica, e perché viene usato Object()?

Ma noi facciamo non sanno che this è un array. Vedere questa nota dalle specifiche di disegno ES6 correnti:

La funzione find è intenzionalmente generica; non richiede che il suo valore this sia un oggetto Array. Pertanto può essere trasferito ad altri tipi di oggetti da utilizzare come metodo. La funzione find può essere applicata correttamente a un oggetto esotico che non è una matrice dipende dall'implementazione.

Troverete questa nota su quasi tutte le funzioni predefinite assegnate ai prototipi.

esempio si possono usare per altre cose, avviene mediante l'assegnazione di oggetti o altri prototipi direttamente:

MyNiftyThing.prototype.find = Array.prototype.find; 

... o tramite Function#call o Function#apply.

Supponiamo quindi di voler utilizzare Array#find su un oggetto arguments.arguments è, ovviamente, come un array ma non un array. Quindi potrei fare questo:

function foo() { 
    var firstObject = Array.prototype.find.call(arguments, function(val) { 
     return typeof val === "object"; 
    }); 
    // ... 
} 

Un altro esempio famoso (che non comportano find) sta usando slice per convertire gli oggetti array come in array:

function foo() { 
    // Turn the `arguments` pseudo-array into a real array 
    var args = Array.prototype.slice.call(arguments, 0); 
} 
+0

grazie mille per un'ottima risposta. –

Problemi correlati