Acabo de leer " JavaScript: The Good Parts " de Crockford y tengo un pregunta sobre su postura sobre los enfoques psuedo-clásico versus prototípico. En realidad no estoy realmente interesado en su postura; Solo quiero entender su argumento para poder establecer una postura propia.

En el libro, Crockford parece inferir que las funciones de constructor y "todo ese jazz" no deberían usarse en JavaScript, menciona cómo la palabra clave 'nueva' está mal implementada, es decir, las funciones que no son de constructor pueden llamarse con 'nuevo' palabra clave y viceversa (potencialmente causando problemas).

Pensé que entendía de dónde venía, pero supongo que no.

Cuando necesito crear un nuevo módulo, normalmente comenzaría así:

function MyModule(something) {
    this.something = something || {};
}

Y luego agregaría algunos métodos a su prototipo:

MyModule.prototype = {
    setSomething : function(){},
    getSomething : function(){},
    doSomething : function(){}
}

Me gusta este modelo; significa que puedo crear una nueva instancia siempre que la necesite y tiene sus propias propiedades y métodos:

var foo = new MyModule({option1: 'bar'});
// Foo is an object; I can do anything to it; all methods of the "class"
// are available to this instance.

Mi pregunta es : ¿Cómo logro lo anterior utilizando un enfoque más adecuado para JavaScript? En otras palabras, si "JavaScript" fuera una persona, ¿qué sugeriría ella?

Además: ¿qué quiere decir Crockford cuando dice que un patrón de diseño particular "es más expresivo" que otro?

18
James 26 abr. 2009 a las 20:26

4 respuestas

La mejor respuesta

Consulte: ¿La "nueva" palabra clave de JavaScript se considera perjudicial?

Es importante recordar que Crockford, como muchos otros programadores de JavaScript, primero se acercó al lenguaje con la intención de "arreglarlo", haciéndolo más parecido a otros lenguajes OO (llamados "clásicos"). Entonces se escribió una gran cantidad de código estructural, se construyeron bibliotecas y marcos, y ... luego comenzaron a darse cuenta de que no era realmente necesario; Si te acercas a JS en sus propios términos, puedes llevarte bien.

10
Community 23 may. 2017 a las 10:29

Javascript no es una persona, por lo que realmente no puede sugerir lo que haces.

Ninguna de las respuestas anteriores ha mencionado el estilo de herencia funcional simple y antiguo, que tiendo a encontrar es el más simple.

function myModuleMaker(someProperty){
  var module = {}; //define your new instance manually

  module.property = someProperty; //set your properties

  module.methodOne = function(someExternalArgument){
    //do stuff to module.property, which you can, since you have closure scope access
  return module;
  }
}

Ahora para hacer una nueva instancia:

var newModule = myModuleMaker(someProperty);

Todavía obtiene todos los beneficios del pseudoclásico de esta manera, pero sufre el único inconveniente de que está haciendo una nueva copia de todos los métodos de su instancia cada vez que crea una instancia. Esto probablemente solo importará cuando comience a tener cientos (o incluso miles) de instancias, lo cual es un problema que la mayoría de la gente rara vez encuentra. Es mejor usar pseudoclassical si está creando estructuras de datos realmente enormes o está haciendo animaciones de núcleo duro con muchas, muchas instancias de algo.

Creo que es difícil argumentar que cualquiera de los métodos es una "mala práctica" per se.

0
Community 8 dic. 2015 a las 04:07

Su implementación es problemática porque está reemplazando todo el objeto prototipo, perdiendo las propiedades del prototipo de función heredada y también rompería, o al menos dificultaría, la capacidad de hacer uso de la herencia más adelante si escribiera otras clases de la misma manera

Un método más adecuado para Javascript sería:

var MyClass = function (storeThis) {
 this.storage = storeThis
}

MyClass.prototype.getStorage = function (){
   return this.storage;
}

MyClass.prototype.setStorage = function (newStorage){
  this.storage = newStorage;
}

Úselo:

var myInstance = new MyClass("sup");
alert("myInstance storage: " + myInstance.getStorage());
myInstance.setStroage("something else");

En cuanto a la palabra clave "nueva" y los problemas de Crawford con ella, realmente no puedo responder, porque no he leído el libro, pero puedo ver cómo puedes crear un nuevo objeto llamando a cualquier función con la nueva palabra clave, incluyendo funciones que se supone que son métodos de una clase.

Y cuando alguien dice algo, como un patrón de diseño, es más "expresivo", generalmente quiere decir que el patrón de diseño es claro y simple de entender qué está logrando y cómo.

2
Bjorn 4 oct. 2009 a las 08:48

La variante prototípica para el ejemplo que tiene se parece a la siguiente en mi entendimiento:

Object.beget = function (o) { /* Crockfords replacement for the new */ }

var myModule = {
    something : null,
    getSomething : function () {},
    setSomething : function () {},
    doSomething : function () {}
};

Y luego puedes hacer:

var foo = Object.beget(myModule);
foo.something = bar;

ACTUALIZACIÓN: también puede usar el patrón de generador para reemplazar un constructor como este:

var myModuleBuilder = {
    buildMyModule : function (something) {
        var m = Object.beget(myModule);
        m.something = something || {};
        return m;
    }
}

Entonces puedes hacer:

var foo = myModuleBuilder.buildMyModule(something);
4
artemb 27 abr. 2009 a las 03:26