Recientemente estoy viendo "JavaScript Advanced Programming" (segunda edición)
Creación de objetos en JavaScript
• Modo de fábrica
• Modo de constructor
• Modo prototipo
• Combinar el constructor y el patrón prototipo
• Modo dinámico prototipo
La mayoría de los idiomas orientados a objetos tienen el concepto de una clase, a través del cual se pueden crear múltiples objetos con los mismos métodos y atributos. Aunque técnicamente, JavaScript es un lenguaje orientado a objetos, JavaScript no tiene el concepto de clases, todo es un objeto. Cualquier objeto es una instancia de cierto tipo de referencia y se crea a través de los tipos de referencia existentes; El tipo de referencia puede ser nativo o personalizado. Los tipos de referencia nativos son: objeto, matriz, datos, regexp, función. ! Un tipo de referencia es una estructura de datos que organiza datos y funciones, generalmente llamada clase. En JavaScript que carece del concepto de clase, el problema que debe resolverse es cómo crear objetos de manera eficiente.
1.1.0. Métodos generales para crear objetos
Var Person = {}; // La representación literal de objetos es equivalente a VAR persona = new ObjCect (); persona.name = 'Evansdiy'; persona.age = '22'; Person.friends = ['Ajiao', 'Tiantian', 'Pangzi']; persona.logname = function () {console.log (this.name);}Según el tipo de referencia de objeto, se crea un objeto, que contiene cuatro propiedades, una de las cuales es un método. Si necesita muchas instancias como persona, habrá mucho código duplicado.
1.1.1. Modelo de fábrica
Cree un objeto con una función que pueda contener los detalles del objeto y luego devuelva el objeto.
Funcion Person (nombre, edad, amigos) {var o = {nombre: nombre, edad: edad, amigos: amigos, logName: function () {console.log (this.name); }}; return o;} var persona1 = persona ('evansdiy', '22', ['ajiao', 'tiantian', 'pangzi']);Cada vez que se llama a la función de la persona, se crea un nuevo objeto a través del objeto o dentro de la función y luego se devuelve. Además de esto, este objeto interno O existe para crear un nuevo objeto no tiene otro propósito. Además, es imposible determinar el tipo de objeto creado por el modo de fábrica.
1.1.2. Modo de constructor
Función persona (nombre, edad, trabajo) {this.name = name; this.age = edad; this.job = trabajo; this.logname = function () {console.log (this.name); }} // Crear una instancia de persona a través del nuevo operador var persona1 = nueva persona ('boy-a', '22', 'trabajador'); var persona2 = nueva persona ('niña-b', '23', 'maestro'); persona1.logname (); //boy-superson2.logname (); // Girl-AComparando el modo de fábrica, podemos encontrar que no hay necesidad de crear objetos intermedios aquí, no hay retorno. Además, la instancia del constructor se puede identificar como un tipo específico, que resuelve el problema del reconocimiento de objetos (al verificar el atributo del constructor de la instancia, o utilizando la instancia de operador para verificar si la instancia es creada por un constructor).
console.log (persona1.constructor == persona); // El constructor se encuentra en el prototipo del constructor y señala el constructor, y el resultado es verdadero
console.log (persona1 instancia de persona); // Use la instancia del operador para determinar si la persona1 es una instancia de la persona constructor, pero el patrón del constructor también tiene sus propios problemas. De hecho, el método logName se recreará una vez en cada instancia. Cabe señalar que los métodos creados por instanciación no son iguales, y el siguiente código se volverá falso:
console.log (persona1.logname == Person2.Logname); // Falso Podemos mover el método fuera del constructor (cambiado a una función global) para resolver este problema:
function logName () {console.log (this.name);} function logage () {console.log (this.age);}Sin embargo, las funciones globales creadas a nivel mundial solo pueden ser llamadas por instancias creadas por persona, lo cual es un poco poco realista; Si hay muchos métodos, aún necesitan ser definidos uno por uno, sin encapsulación.
1.1.3. Modo prototipo
Cada función en JavaScript contiene un puntero al atributo prototipo (la mayoría de los navegadores pueden acceder a él a través del atributo interno __proto__), un atributo prototipo es un objeto que contiene propiedades y métodos compartidos por todas las instancias creadas por un cierto tipo de referencia.
función persona () {} persona.name = 'evansdiy'; persona.prototype.friends = ['ajiao', 'jianjian', 'pangzi']; persona.prototype.logname = function () {console.log (this.name);} var persona1 = nueva persona (); persona1.logname (); // 'El código anterior hace estas cosas:
1. Defina una persona constructora. La función de la persona obtiene automáticamente una propiedad prototipo. Esta propiedad solo contiene una propiedad de constructor que apunta a la persona por defecto;
2. Agregue tres atributos a través de la persona. Prototipo, uno de los cuales se utiliza como método;
3. Cree una instancia de persona y luego llame al método logName () en la instancia. !
Lo que debe tener en cuenta aquí es el proceso de llamada del método logName ():
1. Busque el método logName () en la instancia de Person1 y descubrió que no existe tal método, por lo que me remonta al prototipo de persona1
2. Busque el método logame () en el prototipo de la persona1. Existe este método. Entonces llamamos a este método basado en dicho proceso de búsqueda. Podemos evitar que la instancia acceda al atributo del mismo nombre en el prototipo definiendo el atributo del mismo nombre en el prototipo en la instancia. Cabe señalar que hacerlo no eliminará el atributo del mismo nombre en el prototipo, sino que solo evitará que la instancia acceda.
var persona2 = nueva persona ();
persona2.name = 'Laocai'; Si ya no necesitamos propiedades en la instancia, podemos eliminarla a través del operador Eliminar.
eliminar persona2.name; Use el bucle for-in para enumerar todos los atributos a los que puede acceder una instancia (independientemente de si el atributo existe en la instancia o en el prototipo):
para (i en persona1) {console.log (i);}Al mismo tiempo, también puede usar el método de iSownProperty () para determinar si existe una determinada propiedad en la instancia o en el prototipo. Solo cuando la propiedad exista en la instancia se devuelva verdaderas:
console.log (persona1.hasownproperty ('nombre')); // Verdadero! HasnownProperty proviene del prototipo de objeto y es la única forma en JavaScript para no buscar la cadena prototipo al procesar las propiedades. [a través de JavaScript Secret Garden] Además, también puede usar el método In -Operator y AlownProperty () para determinar si existe una determinada propiedad en la instancia o en el prototipo:
console.log (('amigos' en persona1) &&! Person1.hasownproperty ('amigos')); primero determine si Person1 puede acceder a la propiedad de los amigos. Si es posible, determine si esta propiedad existe en la instancia (¡tenga en cuenta el anterior!). Si no existe en el caso, significa que esta propiedad existe en el prototipo. Como se mencionó anteriormente, el prototipo también es un objeto, por lo que podemos escribir el prototipo usando la representación literal de objetos. El método de escritura anterior para agregar código al prototipo se puede modificar a:
Person.prototype = {nombre: 'Evansdiy', Friends: ['ajiao', 'jianjian', 'pangzi'], logName: function () {console.log (this.name); }}Dado que la sintaxis literal del objeto reescribe todo el prototipo prototipo, el atributo del constructor obtenido de forma predeterminada al crear el constructor apuntará al constructor de objeto:
// después del objeto literal reescribe el prototipo
console.log (persona1.constructor); // objeto Sin embargo, la instancia del operador aún devolverá el resultado deseado:
// después del objeto literal reescribe el prototipo
console.log (persona1 instancia de persona); // Verdadero Por supuesto, puede establecer manualmente el valor del constructor en el prototipo para resolver este problema.
Persona.prototype = {constructor: persona, ......}Si el objeto prototipo se modifica después de crear la instancia del objeto, la modificación del prototipo se reflejará inmediatamente en todas las instancias de objeto:
función persona () {}; var persona1 = nueva persona (); persona.prototype.name = 'evansdiy'; console.log (persona1.name); // 'evansdiy'La conexión entre una instancia y un prototipo es solo un puntero, no una copia del prototipo. El prototipo es en realidad un proceso de búsqueda. Cualquier modificación realizada en el objeto Prototipo se reflejará en todas las instancias de objeto, incluso si el prototipo se modifica después de que se crea la instancia. ¿Qué pasa si el objeto prototipo se reescribe después de crear una instancia de objeto?
función persona () {}; var persona1 = nueva persona1 (); // La instancia creada se refiere al prototipo original // el prototipo Person.prototype = {Friends: ['Ajiao', 'Jianjian', 'Pangzi']} var Person2 = New Person (); // Esta instancia se refiere al nuevo prototipo de cúbilo. console.log (persona1.friends);El código anterior tendrá un error indefinido cuando se ejecute en la última línea. Si usamos para enumerar las propiedades accesibles en Person1, encontraremos que no hay nada adentro, pero Person2 puede acceder al atributo de amigos en el prototipo. ! Reescribir el prototipo corta la conexión entre el prototipo existente y todas las instancias de objetos creadas antes. El prototipo de la instancia del objeto creado anteriormente todavía está allí, pero es antiguo.
// Al crear persona1, el objeto prototipo aún no se ha reescrito. Por lo tanto, el constructor en el objeto prototipo sigue siendo la persona predeterminada () console.log (persona1.constructor); // persona () // pero el constructor de persona2 puntos a objeto () console.log (persona2.constructor); // object ()
Cabe señalar que el patrón prototipo ignora el proceso de aprobación de parámetros para el constructor, y todas las instancias obtienen el mismo valor de atributo. Al mismo tiempo, existe un gran problema con el patrón prototipo, es decir, el valor de tipo de referencia en el objeto prototipo será compartido por todas las instancias, y la modificación del valor de tipo de referencia también se reflejará en todas las instancias de objeto.
función persona () {}; persona.prototype = {amigos: ['ajiao', 'tiantian', 'pangzi']} var persona1 = nueva persona (); var persona2 = nueva persona (); persona1.fiends.push ('laocai'); console.log (persona2.friends); // ['Ajiao', 'Tiantian', 'PanGii' ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', ',', '.Modificar el valor de tipo de referencia de la persona1 amigos significa que los amigos en persona2 también cambiarán. De hecho, los amigos guardados en el prototipo son en realidad solo un puntero al valor de los amigos en el montón (la longitud de este puntero se fija y se guarda en la pila). Cuando una instancia accede al valor del tipo de referencia a través del prototipo, también se accede por puntero en lugar de acceder a la copia en la instancia respectiva (dicha copia no existe).
1.1.4. Crear objetos en combinación con constructor y patrón prototipo
Combinando las ventajas del modo de constructor y prototipo, compensando sus respectivas deficiencias, utilizando constructores para pasar los parámetros de inicialización, definir los atributos de instancia en ellos y usar prototipos para definir métodos comunes y atributos públicos. Este modo se usa más ampliamente.
Función Persona (nombre, edad) {this.name = name; this.age = edad; this.friends = ['ajiao', 'jianjian', 'pangzi'];} persona.prototype = {constructor: persona, logName: function () {console.log (this.name); }} var persona1 = nueva persona ('evansdiy', '22'); var persona2 = nueva persona ('amy', '21'); persona1.logname (); // 'evansdiy'person1.fiends.push (' haixao '); console.log (persona2.friends.length); // 31.1.5. Modo dinámico prototipo
El modo dinámico prototipo encapsula toda la información requerida en el constructor y utiliza la instrucción IF para determinar si existe una determinada propiedad en el prototipo. Si no existe (cuando se solicite al constructor por primera vez), ejecute el código de inicialización del prototipo dentro de la instrucción IF.
Función Persona (nombre, edad) {this.name = name; this.age = edad; if (typeof this.logname! = 'function') {persona.prototype.logname = function () {console.log (this.name); }; Persona.prototype.logage = function () {console.log (this.age); }; }; };} var persona1 = nueva persona ('evansdiy', '22'); // El constructor fue llamado por primera vez, y el prototipo se modificó en este momento. var persona2 = nueva persona ('amy', '21'); // El método logName () ya existe y el prototipo no se modificará nuevamenteCabe señalar que este patrón no puede usar la sintaxis literal de objetos para escribir objetos prototipo (esto anulará los objetos prototipo). Si el prototipo se reescribe, el objeto prototipo accesible para la primera instancia creada por el constructor no contendrá las propiedades del objeto prototipo en la instrucción IF.
Función Persona (nombre, edad) {this.name = name; this.age = edad; if (typeof this.logname! = 'function') {persona.prototype = {logName: function () {console.log (this.name); }, logage: function () {console.log (this.age); }}}};} var persona1 = nueva persona ('evansdiy', '22'); var persona2 = nueva persona ('amy', '21'); persona2.logname (); // 'amy'person1.logname (); // logName no existe existeCabe señalar que cada modelo tiene sus propios escenarios de aplicación, y no importa sus ventajas y desventajas.
El análisis anterior de varios patrones de creación de objetos en JavaScript es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.