En un lenguaje típico orientado a objetos, como Java, está el concepto de clase. La clase es la plantilla de un objeto y un objeto es una instancia de una clase. Sin embargo, en el sistema de lenguaje JavaScript, no hay concepto de clase. JavaScript no se basa en 'clase', sino que se implementa a través de constructores y cadenas prototipo. Sin embargo, ES6 proporciona un método de escritura que está más cerca de los idiomas tradicionales, introduciendo el concepto de clase (clase) como una plantilla de objeto. A través de la palabra clave de clase, puede definir una clase. Básicamente, la clase de ES6 puede considerarse solo un azúcar de sintaxis. La mayoría de sus funciones pueden ser logradas por ES5. El nuevo método de escritura de clase solo hace que el objeto prototipo escrito sea más claro y más como la sintaxis de programación orientada a objetos.
Según mi hábito, daré el directorio del artículo antes de escribirlo.
El siguiente contenido se dividirá en las siguientes subsecciones:
1. Una breve introducción a los constructores
2. Contras de constructores
3. El papel del atributo prototipo
4. Cadena prototipo
5. Atributo de constructor
5.1: El papel del atributo de constructor
6. Instancia del operador
1. Una breve introducción a los constructores
En mi artículo sobre la estrecha relación entre los constructores y los nuevos comandos en JavaScript, el concepto y las características de los constructores, los principios y el uso de nuevos comandos, etc., se introducen en detalle. Si no está familiarizado con los constructores, puede ir y saborearlos con cuidado. Aquí hay una revisión simple.
El llamado constructor es una función que proporciona una plantilla para generar un objeto y describe la estructura básica del objeto. Un constructor puede generar múltiples objetos, cada uno con la misma estructura. En general, un constructor es una plantilla para un objeto, y un objeto es una instancia de un constructor.
Las características del constructor son:
R: La primera letra del nombre de la función del constructor debe ser capitalizado.
B: Use este objeto internamente para señalar a la instancia del objeto que se generará.
C: Use el nuevo operador para llamar al constructor y devolver la instancia del objeto.
Veamos el ejemplo más simple.
function persona () {this.name = 'keith';} var boy = new Person (); console.log (boy.name); // 'Keith'2. Contras de constructores
Todos los objetos de instancias pueden heredar propiedades y métodos en el constructor. Sin embargo, las propiedades no se pueden compartir entre las mismas instancias de objeto.
Funcion Person (nombre, altura) {this.name = name; this.Height = altura; this.hobby = function () {return 'ver películas';}} var boy = new Person ('Keith', 180); var niña = nueva persona ('rascal', 153); console.log (boy.name); // 'Keith' console.log (girl.name); // 'Rascal' console.log (boy.hobby === girl.hobby); //FALSOEn el código anterior, una persona constructora genera dos instancias de objetos de niño y niña, y tiene dos propiedades y un método. Sin embargo, su método de pasatiempo es diferente. Es decir, cada vez que use nuevo para llamar al constructor para volver a colocar una instancia de objeto, se creará un método de pasatiempo. Esto no es necesario ni un desperdicio de recursos, porque todos los métodos de pasatiempo son comportamientos infantiles y pueden ser completamente compartidos por dos instancias de objetos.
Por lo tanto, la desventaja de los constructores es que las propiedades o métodos no se pueden compartir entre las instancias de objetos del mismo constructor.
3. El papel del atributo prototipo
Para resolver la desventaja de no poder compartir propiedades entre las instancias de objetos de los constructores, JS proporciona atributos prototipo.
Cada tipo de datos en JS es un objeto (excepto nulo y indefinido), y cada objeto hereda de otro objeto, este último se llama objeto "prototipo", excepto NULL, que no tiene su propio objeto prototipo.
Todas las propiedades y métodos en el objeto prototipo serán compartidos por la instancia del objeto.
Cuando se genera una instancia de objeto a través de un constructor, el prototipo de la instancia del objeto se apunta a la propiedad prototipo del constructor. Cada constructor tiene un atributo prototipo, que es el objeto prototipo de la instancia del objeto.
Funcion Person (nombre, altura) {this.name = name; this.Height = altura; } Persona.prototype.hobby = function () {return 'ver películas'; } var boy = nueva persona ('Keith', 180); var niña = nueva persona ('rascal', 153); console.log (boy.name); // 'Keith' console.log (girl.name); // 'Rascal' console.log (boy.hobby === girl.hobby); //verdaderoEn el código anterior, si el método de hobby se coloca en el objeto prototipo, entonces ambos objetos de instancia comparten el mismo método. Espero que todos puedan entender que para los constructores, el prototipo es una propiedad como constructor; Para instancias de objetos, el prototipo es un objeto prototipo de instancias de objetos. Por lo tanto, el prototipo es una propiedad y un objeto.
Los objetos prototipo no son propiedades de las instancias de objetos. Los atributos de una instancia de objeto son atributos heredados de la definición del constructor, porque hay una palabra clave dentro del constructor para apuntar a la instancia del objeto a generar. Las propiedades de una instancia de objeto son en realidad atributos definidos internamente por el constructor. Mientras se modifiquen las propiedades y métodos en el objeto prototipo, los cambios se reflejarán inmediatamente en todas las instancias de objeto.
Persona.prototype.hobby = function () {return 'Swimming'; } console.log (boy.hobby === girl.hobby); // verdadero console.log (boy.hobby ()); // 'Swimming'Console.log (girl.hobby ()); //'nadar'En el código anterior, después de modificar el método de pasatiempo del objeto prototipo, ambas instancias de objeto han cambiado. Esto se debe a que las instancias de objetos en realidad no tienen métodos de pasatiempo, todos son métodos de pasatiempo que leen objetos prototipo. Es decir, cuando una instancia de objeto no tiene la propiedad y el método, buscará en el objeto prototipo. Si el objeto de instancia en sí tiene una determinada propiedad o método, no se buscará en el objeto prototipo.
boy.hobby = function () {return 'Play Basketball'; } console.log (boy.hobby ()); // 'Play Basketball' Console.log (girl.hobby ()); //'nadar'En el código anterior, cuando se modifica el método de pasatiempo de la instancia del objeto Boy, no se heredará el método de pasatiempo en el objeto prototipo. Sin embargo, la niña aún heredará el método del objeto prototipo.
Para resumir:
R: La función de un objeto prototipo es definir las propiedades y métodos compartidos por todas las instancias de objetos.
B: prototipo, para constructores, es una propiedad; Para instancias de objetos, es un objeto prototipo.
4. Cadenas prototipo
Las propiedades y métodos de un objeto pueden definirse en sí mismo o en su objeto prototipo. Dado que el objeto prototipo en sí es un objeto a las instancias de objeto y también tiene su propio prototipo, se forma una cadena prototipo. Por ejemplo, el objeto A es el prototipo del objeto B, el objeto B es el prototipo del objeto C, y así sucesivamente. La parte superior del prototipo de todos los objetos es el objeto.prototipo, es decir, el objeto señalado por la propiedad prototipo del constructor de objeto.
Por supuesto, el objeto Object.prototype también tiene su propio objeto prototipo, es decir, un objeto nulo sin ningún atributo y método, y el objeto nulo no tiene su propio prototipo.
1 console.log (object.getPrototypeOf (objeto.prototype)); //nulo
2 console.log (persona.prototype.isprototypeOf (boy)) // Verdadero
Las características de las cadenas prototipo son:
R: Al leer una determinada propiedad de un objeto, el motor JavaScript primero busca la propiedad del objeto en sí. Si no se puede encontrar, irá a su prototipo. Si aún no se puede encontrar, irá al prototipo del prototipo. Si el objeto.prototipo en el nivel superior aún no se encuentra, se devuelve undefined.
B: Si el objeto en sí y su prototipo definen un atributo del mismo nombre, entonces los atributos del objeto en sí se leen primero, que se denomina "primordial".
C: Buscar un cierto atributo en el nivel de la cadena prototipo hacia arriba tiene un impacto en el rendimiento. Cuanto mayor sea el nivel del objeto prototipo que está buscando, mayor será el impacto en el rendimiento. Si busca una propiedad inexistente, atravesará toda la cadena prototipo.
Puede ser oscuro mirar el concepto, tomemos un ejemplo. Pero es realmente importante entender el concepto.
var arr = [1,2,3]; console.log (arr.length); //3console.log (arr.valueof ()) // [1,2,3] console.log (arr.join ('|')) // 1 | 2 | 3En el código anterior, se define una matriz ARR, con tres elementos en la matriz. No agregamos ningún atributo o método a la matriz, pero no informamos un error al llamar a la longitud, unir () y valueOf ().
El atributo de longitud se hereda del array.prototype y pertenece a una propiedad en el objeto prototipo. El método de unión también se hereda del array.prototype y pertenece a un método en el objeto prototipo. Estos dos métodos son compartidos por todas las matrices. Cuando no hay un atributo de longitud en el objeto de instancia, se buscará el objeto prototipo.
El método ValueOf se hereda de Object.Prototype. En primer lugar, la matriz ARR no tiene un valor de método, así que busque el prototipo de objeto matriz.prototype. Luego, descubrí que no hay valor de método en el objeto Array.Prototype. Finalmente, busque el objeto Object.Prototype.
Echemos un vistazo a las propiedades y métodos del objeto Array.Prototype y el objeto Object.Prototype respectivamente.
console.log (object.getOwnPropertynames (array.prototype)) // ["longitud", "tosource", "toString", "tOlocaleString", "unirse", "reverso", "sort", "PUSH", "Pop", "desplazamiento", "inhatado", "empalme", "Concat", "corte", "LastIndex", "Pop", ",", ",", ",", ",", "," Concat "," corte "," LastIndex ". "Mapa", "Filtrar", "Reduceright", "Some", "Every", "Find", "FindIndex", "CopywithIn", "Fill", "Entries", "Keys", "Keys", "Values", "Incluye", "Constructor", "$ Set", "Eliminar"] Console.log (Object.getOwnPrepertynames (Object.Proototipo) "toString", "toLocaleString", "valueOf", "watch", "unwatch", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__", "__proto__", "constructor"]
Creo que cuando ves esto, todavía tienes una ligera comprensión del prototipo. Esto es normal. Después de todo, es un concepto más importante y abstracto en JS. Es imposible dominarlo tan rápido. Si comiste algunos artículos más, puedes dominar la esencia. De cierta manera, hay un ejemplo vivo, que también puede ser un problema que todos encontrarán. Puede echar un vistazo a los objetos JS Constructor y Prototype.
5. Atributo de constructor
El objeto prototipo tiene un atributo de constructor que apunta a la función del constructor donde el objeto prototipo se encuentra de forma predeterminada.
función a () {}; console.log (a.prototype.constructor === a) // VerdaderoCabe señalar que el prototipo es la propiedad del constructor, y el constructor es el objeto señalado por la propiedad prototipo del constructor, es decir, propiedad del objeto prototipo. Tenga cuidado de no confundir.
console.log (a.hasownproperty ('prototipo')); // verdadero console.log (a.prototype.hasownproperty ('constructor')); //verdaderoDado que el atributo del constructor se define en el objeto prototipo, significa que puede ser heredado por todos los objetos de instancia.
función a () {}; var a = nuevo a (); console.log (A.Constructor); //A()console.log(a.Constructor===a.prototype.constructor) ;//trueEn el código anterior, A es un objeto de instancia de constructor A, pero A en sí no tiene un atributo de constructor, que en realidad está leyendo la cadena prototipo.
A.Prototype. Propiedad de constructor.
5.1: El papel del atributo de constructor
R: Determine a qué función del constructor es el objeto prototipo que pertenece
función a () {}; var a = nuevo a (); console.log (a.constructor === a) // true console.log (a.constructor === array) // falsoEl código anterior significa que utilizando la propiedad del constructor, se determina que la función del constructor del objeto de instancia a es a, no una matriz.
B: Cree otra instancia a partir de la instancia
función a () {}; var a = new a (); var b = new A.Constructor (); console.log (b instancia de a); //verdaderoEn el código anterior, a es un objeto de instancia de constructor A, y el constructor puede llamarse indirectamente desde A. -Constructor.
C: Es posible llamar a su propio constructor
A.prototype.hello = function () {return nuevo this.Constructor (); }D: Proporciona un patrón de heredar otro constructor de un constructor
function pheet () {} function son () {son.height.constructor.call (this); } Son.Height = new Padre ();En el código anterior, el padre y el hijo son ambos constructores. Llamar al padre en este hijo interior formará el efecto del hijo que heredará al padre.
E: Dado que el atributo del constructor es una relación entre un objeto prototipo y un constructor, al modificar el objeto prototipo, debe prestar atención al problema de señalización del constructor.
Hay dos soluciones: ya sea el atributo del constructor a la función del constructor original o simplemente agregue propiedades y métodos al objeto prototipo para evitar la instancia de instancia.
6. Instancia del operador
La instancia del operador devuelve un valor booleano que indica si el objeto especificado es una instancia de un constructor.
función a () {}; var a = new a (); console.log (una instancia de a); //verdaderoDebido a que InstanceOF es válido para objetos en toda la cadena prototipo, el mismo objeto de instancia puede devolver verdadero para múltiples constructores.
función a () {}; var a = nuevo a (); console.log (una instancia de a); //trueconsole.log(a instancia de objeto); //verdaderoTenga en cuenta que la instancia de los objetos solo se puede utilizar para tipos de datos complejos (matrices, objetos, etc.) y no se puede utilizar para tipos de datos simples (valores booleanos, números, cadenas, etc.).
var x = [1]; var o = {}; var b = verdadero; var c = 'cadena'; console.log (x instancia de matriz); //trueconsole.log(o instancia de objeto); // verdadero console.log (b instancia de boolean); //falseconsole.log(c instancia de cadena); //FALSOAdemás, ni nulo ni indefinido son objetos, por lo que la instancia de siempre devuelve falso.
console.log (instancia nula de objeto); // false console.log (instancia indefinida de objeto); //FALSO
Usando la instancia de operador, también puede resolver hábilmente el problema de olvidar agregar un nuevo comando al llamar al constructor.
function keith (nombre, altura) {if (! esta instancia de keith) {return new Keith (nombre, altura); } this.name = name; this.Height = Height;}En el código anterior, la instancia del operador se usa para determinar si la palabra clave en el cuerpo de la función apunta a una instancia del constructor keith. Si no, significa que el nuevo comando se olvida. En este momento, el constructor devolverá una instancia de objeto para evitar resultados inesperados.
Debido a las limitaciones de espacio, lo presentaré aquí por el momento.
En mi próxima parte, hablaré sobre algunos métodos nativos de objetos prototipo, como Object.getPrototipof (), Object.SetPrototipof (), etc., e introducirá una comparación de métodos para obtener objetos nativos.
Lo anterior es la explicación detallada del atributo prototipo (recomendado) en JavaScript presentada por el editor. Espero que te sea útil.