Come definire il metodo in javascript su Array.prototype e Object.prototype in modo che non appaia nel ciclo for in

Voglio definire i metodi di supporto su Array.prototype e Object.prototype. Il mio piano attuale è di fare qualcosa come:

Array.prototype.find = function(testFun) { // code to find element in array }; 

In modo che io possa fare questo:

 var arr = [1, 2, 3]; var found = arr.find(function(el) { return el > 2; }); 

Funziona bene, ma se faccio un loop sull’array in un ciclo for in i metodi appaiono come valori:

 for (var prop in arr) { console.log(prop); } // prints out: // 1 // 2 // 3 // find 

Questo rovinerà tutti gli altri che si affidano al for in per mostrare solo i valori (specialmente su Objects). Le versioni successive di javascript hanno funzioni .map e .filter incorporate negli array, ma quelle non si visualizzano for in cicli in. Come posso creare più metodi come quelli che non verranno visualizzati in un ciclo for in ?

È abbastanza semplice: non utilizzare i cicli for-in con gli array . Dai la colpa a tutti gli altri che lo fanno – ecco un bel frammento da raccontare durante lo sviluppo.

Naturalmente, se si esegue un’enumerazione in una funzione generica e non si sa se ottiene un array, un object semplice o un object con un prototipo personalizzato, è ansible utilizzare hasOwnProperty questo modo:

 for (var prop in anyObj ) if (Object.prototype.hasOwnProperty.call(anyObj, prop)) // do something 

Si noti l’uso esplicito di Object.prototype per ottenere la funzione – potrebbero esserci oggetti che lo sovrascrivono (specialmente nelle mappe di dati, il valore potrebbe non essere nemmeno una funzione), oggetti che non lo supportano o oggetti che non ereditano da Object.prototype affatto. Vedi anche qui .

Tuttavia, solo un autore di sceneggiature che è a conoscenza del problema filtrerebbe tutti i suoi for-in-loops – e alcuni lo fanno solo perché è raccomandato – e lo fa per lo più, avrebbe dovuto usare invece un’iterazione di matrice per ciclo. Ma il nostro problema sono quegli autori che non lo sanno.

Un approccio interessante, ma basato su Mozilla, potrebbe sovrascrivere il comportamento delle enumerazioni sugli array tramite __iterate__ , come dimostrato qui .

Fortunatamente, EcmaScript 5.1 ci consente di impostare le proprietà come non enumerabili . Naturalmente, questo non è supportato nei browser più vecchi, ma perché preoccuparsi? Avremmo comunque bisogno di usare es5-shims per tutti gli elementi dell’array di ordine superiore 🙂 Usa defineProperty questo modo:

 Object.defineProperty(Array.prototype, "find", { enumerable: false, writable: true, value: function(testFun) { // code to find element in array } }); 

A seconda delle tue restrizioni:

 // In EcmaScript 5 specs and browsers that support it you can use the Object.defineProperty // to make it not enumerable set the enumerable property to false Object.defineProperty(Array.prototype, 'find', { enumerable: false, // this will make it not iterable get: function(testFun) { // code to find element in array }; }); 

Maggiori informazioni su Object.defineProperty qui https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

È perché è necessario verificare hasOwnProperty :

 for (var prop in arr) { if (arr.hasOwnProperty(prop)) { console.log(prop) } } 

Ora questo registra 1, 2, 3.