Objetos JavaScript y Crockford's The Good Parts


8

He estado pensando bastante sobre cómo hacer OOP en JS, especialmente cuando se trata de encapsulación y herencia, recientemente.

Según Crockford, el clásico es dañino debido a new (), y tanto el prototipo como el clásico están limitados porque su uso de constructor.prototype significa que no puede usar cierres para la encapsulación.

Recientemente, he considerado los siguientes dos puntos sobre la encapsulación:

  1. La encapsulación mata el rendimiento . Le hace agregar funciones a CADA objeto miembro en lugar de al prototipo, porque los métodos de cada objeto tienen cierres diferentes (cada objeto tiene miembros privados diferentes).

  2. La encapsulación obliga a la desagradable solución "var that = this" a obtener funciones auxiliares privadas para tener acceso a la instancia a la que están conectadas. O eso, o asegúrese de llamarlos con privateFunction.apply (this) cada vez.

¿Hay soluciones para cualquiera de los dos problemas que mencioné? si no, ¿todavía considera que la encapsulación vale la pena?

Nota al margen: El patrón funcional que describe Crockford ni siquiera le permite agregar métodos públicos que solo toquen a los miembros públicos, ya que renuncia por completo al uso de new () y constructor.prototype. ¿No sería superior un enfoque híbrido en el que usa la herencia clásica y new (), pero también llama a Super.apply (esto, argumentos) para inicializar miembros privados y métodos privilegiados?


Creo que hay algunas bibliotecas de JavaScript que proporcionan todo esto, por ejemplo, Dojo . También hay TypeScript .
MarkJ 01 de

El sistema de clases de @MarkJ Dojo parece idéntico a las miles de bibliotecas de herencia pseudo-clásicas, y no ofrece nada con respecto a la encapsulación.
Jonathan el

Por cierto, ese artículo está minimizando el uso de memoria. No considera en absoluto que el uso de la memoria aumente con la cantidad de métodos ... por ejemplo, si tuviera 20 métodos en la "clase", el patrón funcional tomaría 3000 mb con sus números, pero el prototipo todavía tomaría 150 mb independientemente de La cantidad de métodos. Es como comparar O(1)a O(n)con n = 2...
Esailija

Respuestas:


2

La encapsulación es realmente complicada y probablemente no valga la pena en JavaScript. Un método que funcione y haga todo lo que desee (campos privados, acceso a la superclase y métodos privados) sería esta solución (probablemente muy fea y mejorable):

function SomeClass() {

    var parent = SomeSuperClass(),
        somePrivateVar;

    return Object.create(parent, {
        somePrivateVar: {
            get: function() {
                return somePrivateVar;
            },
            set: function(value) {
                somePrivateVar = value;
            }
        },
        doSomething: {
            value: function(data) {
                someHelperFunction.call(this, data);
            }
        }
    });
}

function someHelperFunction(data) {
    this.someMethod(data);
}

Este tipo de trabajo le permite tener campos y métodos privados y herencia como uno esperaría. Sin embargo, no me gusta, pero me gusta la mejor de todas las posibilidades que tienes en JavaScript puro.

Si tuviera que comenzar un nuevo proyecto con mucho JavaScript, probablemente tendría una mirada más cercana a TypeScript . Mejora JavaScript cuando es necesario (en mi humilde opinión), le ofrece tipeo estático, herencia, encapsulación y todo ... Pero es solo JavaScript, después de todo.


Ahora, ¿vale la pena? Creo que hay dos cosas importantes a considerar. La encapsulación probablemente lo ayude en el momento del desarrollo, pero ciertamente no lo hace en tiempo de ejecución. Creo que tienes que decidir; O bien sin encapsulación y mejor rendimiento, o encapsulación, código no tan hermoso, probablemente un mejor diseño pero algo de sobrecarga en tiempo de ejecución.


Soy consciente de este patrón: es lo que Crockford llama funcional, con la ligera diferencia de que configura al padre como el prototipo del niño. La pregunta es precisamente: ¿vale la pena la sobrecarga mencionada en mi OP (y presente en su código)? ¿Hay alguna forma de evitar dicha sobrecarga? TypeScript parece interesante porque la verificación de encapsulación se realiza en tiempo de compilación, lo que significa que no hay sobrecarga en el JS compilado, pero por el momento, me quedo con JS sin formato. Por cierto, por coherencia, su código probablemente debería leer var parent = SomeSuperClass (), sin nuevo.
Jonathan el

@ Jonathan: Agregué más información sobre la pregunta "vale la pena".
Bruno Schäpper
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.