update remove property objects from exclude delete array javascript prototype

javascript - remove - Object.prototype is Verboten?



remove object by key from array javascript (3)

RESUMEN:

Ok, ha pasado un tiempo desde que hice esta pregunta. Como de costumbre, fui y Object.prototype el Object.prototype del Object.prototype todos modos, a pesar de todos los argumentos válidos en contra de él, tanto aquí como en otros lugares en la web. Supongo que soy ese tipo de imbécil obstinado.

Traté de encontrar una manera concluyente de evitar que el nuevo método destruya cualquier comportamiento esperado, lo que demostró ser una tarea muy difícil pero informativa.
He aprendido muchas cosas sobre JavaScript. No en lo más mínimo, no intentaré nada tan atrevido como meterme con los prototipos nativos (excepto String.prototype.trim para IE <9).

En este caso particular, no uso ninguna biblioteca, por lo que los conflictos no fueron mi principal preocupación. Pero después de haber profundizado un poco más en posibles contratiempos al jugar con prototipos nativos, no es probable que pruebe este código en combinación con cualquier lib.

Al analizar este enfoque prototipo, he llegado a una mejor comprensión del modelo en sí. Trataba los prototipos como una forma de clase abstracta tradicional flexible, haciéndome aferrarme al pensamiento tradicional de OOP. Este punto de vista realmente no hace justicia al modelo prototipo. Douglas Crockford escribió sobre este escollo, lamentablemente el fondo rosa me impidió leer el artículo completo.

Decidí actualizar esta pregunta en caso de que la gente que la lea esté tentada a ver por sí misma. Todo lo que puedo decir es que, por todos los medios, hazlo. Espero que aprendas un par de cosas interesantes, como lo hice yo, antes de decidir abandonar esta idea bastante tonta. Una función simple podría funcionar igual de bien, o incluso mejor, especialmente en este caso. Después de todo, la verdadera belleza de esto es que al agregar solo 3 líneas de código, puede usar esa misma función para aumentar los prototipos de objetos específicos de todos modos.

Sé que estoy a punto de hacer una pregunta que ha existido durante bastante tiempo, pero: ¿por qué se considera que el prototipo Object está fuera de límites ? Está allí, y se puede aumentar de todos modos, como cualquier otro prototipo. ¿Por qué, entonces, no deberías aprovechar esto? En mi opinión, mientras sepas lo que estás haciendo, no hay razón para alejarte del prototipo de Objeto.
Tomemos este método por ejemplo:

if (!Object.prototype.getProperties) { Object.prototype.getProperties = function(f) { "use strict"; var i,ret; f = f || false; ret = []; for (i in this) { if (this.hasOwnProperty(i)) { if (f === false && typeof this[i] === ''function'') { continue; } ret.push(i); } } return ret; }; }

Básicamente, es el mismo viejo for...in bucle que mantendrías seguro en una función, o escribir una y otra vez. Sé que se agregará a todos los objetos, y dado que casi todas las cadenas de herencia en JavaScript se pueden rastrear hasta el Object.prototype , pero en mi script, lo considero el menor de los dos males.

Tal vez, alguien podría hacer un mejor trabajo al decirme dónde me equivoco que entre otros.
Mientras buscaban las razones por las que la gente daba NO tocar el prototipo del Object , una cosa seguía apareciendo: rompe el for..in loop- for..in , pero nuevamente: muchos marcos también lo hacen, por no mencionar sus propias cadenas de herencia. Por lo tanto, es una mala práctica no incluir en mi mente una verificación de .hasOwnProperty cuando recorre las propiedades de un objeto.

También me pareció bastante interesante. Nuevamente, un comentario es bastante inequívoco: extender prototipos nativos es una mala práctica, pero si la gente del V8 lo hace, ¿quién soy yo para decir que están equivocados?
Lo sé, ese argumento no se apila del todo.

El punto es: realmente no puedo ver un problema con el código anterior. Me gusta, lo uso mucho y hasta ahora, no me ha fallado una vez. Incluso estoy pensando en adjuntar un par de funciones más al prototipo de Objeto. A menos que alguien pueda decirme por qué no debería, eso es.


Consulte http://www.websanova.com/tutorials/javascript/extending-javascript-the-right-way

Que aborda algunas, pero no todas, las objeciones planteadas. La objeción sobre diferentes bibliotecas que crean métodos de conflicto se puede aliviar al generar una excepción si un método específico de dominio ya está presente en Object.prototype. Al menos, esto proporcionará una alerta cuando ocurra este evento no deseado.

Inspirado por esta publicación, desarrollé lo siguiente, que también está disponible en los comentarios de la página citada.

!Object.implement && Object.defineProperty (Object.prototype, ''implement'', { // based on http://www.websanova.com/tutorials/javascript/extending-javascript-the-right-way value: function (mthd, fnc, cfg) { // adds fnc to prototype under name mthd if (typeof mthd === ''function'') { // find mthd from function source cfg = fnc, fnc = mthd; (mthd = (fnc.toString ().match (/^function/s+([a-z$_][/w$]+)/i) || [0, ''''])[1]); } mthd && !this.prototype[mthd] && Object.defineProperty (this.prototype, mthd, {configurable: !!cfg, value: fnc, enumerable: false}); } }); Object.implement (function forEach (fnc) { for (var key in this) this.hasOwnProperty (key) && fnc (this[key], key, this); });

Lo he usado principalmente para agregar una función definida estándar en la implementación que no los admite.


El hecho es que está bien, siempre y cuando sepas lo que estás haciendo y cuáles son los costos. Pero es un gran "si". Algunos ejemplos de los costos:

  • Deberá realizar pruebas exhaustivas con cualquier biblioteca que elija utilizar con un entorno que Object.prototype . porque la convención abrumadora es que un objeto en blanco no tendrá propiedades enumerables. Al agregar una propiedad enumerable a Object.prototype , está haciendo que esa convención sea falsa. Por ejemplo, esto es bastante común:

    var obj = {"a": 1, "b": 2}; var name; for (name in obj) { console.log(name); }

    ... con la abrumadora convención de que solo aparecerán "a" y "b", no "getProperties".

  • Cualquier persona que trabaje en el código deberá ser instruida en el hecho de que esa convención (arriba) no se cumple.

Puede mitigar lo anterior usando Object.defineProperty (y similar) si es compatible, pero tenga en cuenta que incluso en 2014, los navegadores como IE8 que no lo admiten siguen teniendo un uso significativo (aunque podemos esperar que eso cambie rápidamente ahora que XP) es oficialmente EOL''d). Esto se debe a que al usar Object.defineProperty , puede agregar propiedades no enumerables (las que no aparecen for-in bucles for-in ) y así tendrá menos problemas (en ese momento, le preocupa principalmente el nombre conflictos), pero solo funciona en sistemas que implementan Object.defineProperty correctamente (y una implementación correcta no puede ser "modificada").

En su ejemplo, no agregaría getProperties a Object.prototype ; Lo agregaría a Object y aceptaría el objeto como un argumento, como hace ES5 para getPrototypeOf y similar.

Tenga en cuenta que la biblioteca Prototype recibe muchas críticas por la extensión del Array.prototype debido a cómo afecta for..in bucles ... en. Y eso es solo Array s (que no debería usar para ... for..in de todos modos (a menos que esté usando la protección hasOwnProperty y probablemente String(Number(name)) === name también).

... si la gente del V8 lo hace, ¿quién soy yo para decir que están equivocados?

En V8, puede confiar en Object.defineProperty , porque V8 es un motor totalmente compatible con ES5.

Tenga en cuenta que incluso cuando las propiedades no son enumerables, hay problemas. Hace años, Prototype (indirectamente) definió una función de filter en Array.prototype . Y hace lo que cabría esperar: llama a una función de iterador y crea una nueva matriz basada en los elementos que la función elige. Luego apareció ECMAScript5 y definió Array.prototype.filter para hacer casi lo mismo. Pero ahí está el problema: mucho lo mismo. En particular, la firma de las funciones de iterador a las que se llama es diferente (ECMAScript5 incluye un argumento que Prototype no). Podría haber sido mucho peor que eso (y sospecho, pero no puedo demostrarlo, que TC39 era consciente de Prototype y evitó intencionalmente muchos conflictos con él).

Entonces: si lo va a hacer, tenga en cuenta los riesgos y los costos. Los errores feos de borde que puede encontrar como resultado de intentar usar bibliotecas listas para usar realmente podrían costarle tiempo ...


Si los marcos y las bibliotecas generalmente hicieran lo que está proponiendo, muy pronto sucederá que dos marcos diferentes definirían dos funcionalidades diferentes como el mismo método de Object (o Array , Number ... o cualquiera de los prototipos de objetos existentes). Por lo tanto, es mejor agregar dicha nueva funcionalidad en su propio espacio de nombres.

Por ejemplo ... imagínese, tendría una biblioteca que serializaría objetos a json y una biblioteca que los serializaría a XML y ambos definirían su funcionalidad como

Object.prototype.serialize = function() { ... }

y solo podrías usar el que se definió más adelante. Así que es mejor si no lo hacen, sino que

JSONSerializingLibrary.seralize = function(obj) { ... } XMLSerializingLibrary.seralize = function(obj) { ... }

También podría ocurrir que una nueva funcionalidad se defina en un nuevo estándar de ECMAscript o que un proveedor de navegadores agregue. Así que imagina que tus navegadores también agregarían una función de serialize . Eso volvería a causar conflictos con las bibliotecas que definieron la misma función. Incluso si la funcionalidad de las bibliotecas era la misma que la que está incorporada en el navegador, las funciones de script interpretadas anularían la función nativa que, de hecho, sería más rápida.