Cómo definir el método en javascript en Array.prototype y Object.prototype para que no aparezca en bucle for in

4 minutos de lectura

Como definir el metodo en javascript en Arrayprototype y Objectprototype
brady

Quiero definir métodos auxiliares en Array.prototype y Object.prototype. Mi plan actual es hacer algo como:

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

Para que pueda hacer esto:

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

Funciona bien, pero si recorro la matriz en un for in loop los métodos aparecen como valores:

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

Esto arruinará a cualquiera que confíe en el for in para mostrar valores (especialmente en Objetos). Las versiones posteriores de javascript tienen funciones .map y .filter integradas en matrices, pero esas no aparecen en for in bucles ¿Cómo puedo crear más métodos como ese que no aparecerán en un for in ¿lazo?

1646961610 351 Como definir el metodo en javascript en Arrayprototype y Objectprototype
Bergi

Es bastante fácil: no use bucles for-in con Arrays. Culpe a todos los demás que lo hacen: aquí hay un buen fragmento para contarles durante el desarrollo.

Por supuesto, si uno hace una enumeración en una función genérica y no sabe si obtiene una matriz, un objeto simple o un objeto con un prototipo personalizado, puede usar hasOwnProperty Me gusta esto:

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

Nótese el uso explícito de Object.prototype para obtener la función: puede haber objetos que lo sobrescriban (especialmente en los mapas de datos, el valor podría ni siquiera ser una función), objetos que no lo admiten u objetos que no heredan de Object.prototype en absoluto. Ver también aquí.

Sin embargo, solo un autor de secuencias de comandos que es consciente del problema filtraría todos sus bucles for-in, y algunos solo lo hacen porque se recomienda, y lo hace en su mayoría mal, debería haber usado una iteración de matriz for-loop en su lugar. Pero nuestro problema son aquellos autores que no lo saben.

Un enfoque interesante, pero exclusivo de Mozilla, sería sobrescribir el comportamiento de las enumeraciones en matrices a través de __iterate__como se demuestra aquí.

Afortunadamente, EcmaScript 5.1 nos permite establecer propiedades para ser no enumerable. Por supuesto, esto no es compatible con los navegadores más antiguos, pero ¿por qué molestarse? Necesitaríamos usar es5-shims de todos modos, para todas las cosas geniales de matriz de orden superior 🙂 defineProperty Me gusta esto:

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

  • Me gusta poner ese largo hasOwnProperty en una función de ayuda. Tener una taquigrafía como hop(anyObj, prop) hace que sea menos probable que use una de las alternativas más cortas pero subóptimas que mencionó.

    – hugomg

    8 de noviembre de 2012 a las 20:20


  • Claro, puedes definir var hop = Function.prototype.call.bind(Object.prototype.hasOwnProperty), pero como el programador promedio nunca debería necesitarlo, no lo he mencionado. Aquellas bibliotecas que proporcionan funciones altamente genéricas lo usan internamente, por supuesto.

    – Bergi

    8 de noviembre de 2012 a las 20:25


Dependiendo de sus restricciones:

// 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
    };
});

Leer más sobre Objeto.defineProperty aquí https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

  • No, no desea definir una función captadora para este método prototipo. Mira mi respuesta…

    – Bergi

    8 de noviembre de 2012 a las 20:07

  • No puede confiar en que nadie más que use su código hará la verificación hasOwnProperty, por lo que esta es una forma segura.

    – Greg Hornby

    21 de junio de 2016 a las 5:06

Es porque hay que buscar hasOwnProperty:

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

Ahora esto registra 1, 2, 3.

  • bergi estaba tratando de decir que este código se rompe si alguien agrega una propiedad “hasOwnProperty” a arr o su prototipo.

    – hugomg

    8 de noviembre de 2012 a las 20:22

Las respuestas anteriores pierden un punto:

enumerable… Predeterminado a falso. (mdn)

Así que simplemente usando Object.defineProperty(Array.prototype, 'myFunc' myFunc) en lugar de Array.prototype.myFunc = myFunc resolverá el problema.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad