Cómo funciona JavaScript.¿trabajo de prototipo?


No me gustan los lenguajes de programación dinámicos, pero he escrito mi parte justa de código JavaScript. Nunca me di cuenta de esta programación basada en prototipos, ¿sabe alguien cómo funciona?

var obj = new Object();
obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

Recuerdo mucha discusión que tuve con la gente hace un tiempo (no estoy exactamente seguro de lo que estoy haciendo), pero según lo entiendo, no hay concepto de clase. Es sólo un objeto, y las instancias de esos objetos son clones del original, ¿verdad?

Pero ¿qué es el propósito exacto de esto".prototype " propiedad en JavaScript? ¿Cómo se relaciona con la creación de instancias de objetos?

Actualización: camino correcto

var obj = new Object(); // not a functional object
obj.prototype.test = function() { alert('Hello?'); }; // this is wrong!

function MyObject() {} // a first class functional object
MyObject.prototype.test = function() { alert('OK'); } // OK

También estas diapositivas realmente ayudaron mucho.

Author: John Leidegren, 2009-02-21

23 answers

Cada objeto JavaScript tiene una propiedad interna llamada [[Prototype]] . Si busca una propiedad a través de obj.propName o obj['propName'] y el objeto no tiene tal propiedad - que se puede verificar a través de obj.hasOwnProperty('propName') - el tiempo de ejecución busca la propiedad en el objeto al que hace referencia [[Prototype]] en su lugar. Si el objeto prototipo tampoco tiene tal propiedad, su prototipo se comprueba a su vez, recorriendo así la cadena de prototipos del objeto original hasta que se encuentra una coincidencia o su final es llegar.

Algunas implementaciones de JavaScript permiten el acceso directo a la propiedad [[Prototype]], por ejemplo, a través de una propiedad no estándar llamada __proto__. En general, solo es posible establecer el prototipo de un objeto durante la creación del objeto: Si crea un nuevo objeto a través de new Func(), la propiedad [[Prototype]] del objeto se establecerá en el objeto al que hace referencia Func.prototype.

Esto permite simular clases en JavaScript, aunque el sistema de herencia de JavaScript es - como hemos visto-prototípico, y no basado en clases:

Solo piense en las funciones constructoras como clases y las propiedades del prototipo (es decir, del objeto al que hace referencia la propiedad prototype de la función constructora) como miembros compartidos, es decir, miembros que son los mismos para cada instancia. En los sistemas basados en clases, los métodos se implementan de la misma manera para cada instancia, por lo que los métodos normalmente se agregan al prototipo, mientras que los campos de un objeto son específicos de la instancia y, por lo tanto, se agregan al objeto en sí durante la construcción.

 941
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-27 13:23:22

En un lenguaje que implementa herencia clásica como Java, C# o C++, comienza creando una clase a un blueprint para sus objetos and y luego puede crear nuevos objetos a partir de esa clase o puede extender la clase, definiendo una nueva clase que aumente la clase original.

En JavaScript primero crea un objeto (no hay concepto de clase), luego puede aumentar su propio objeto o crear nuevos objetos a partir de él. No es difícil, pero un poco extraño y difícil de metabolizar para alguien acostumbrado a la forma clásica.

Ejemplo:

//Define a functional object to hold persons in JavaScript
var Person = function(name) {
  this.name = name;
};

//Add dynamically to the already defined object a new getter
Person.prototype.getName = function() {
  return this.name;
};

//Create a new object of type Person
var john = new Person("John");

//Try the getter
alert(john.getName());

//If now I modify person, also John gets the updates
Person.prototype.sayMyName = function() {
  alert('Hello, my name is ' + this.getName());
};

//Call the new method on john
john.sayMyName();

Hasta ahora he estado extendiendo el objeto base, ahora creo otro objeto y luego heredando de Person.

//Create a new object of type Customer by defining its constructor. It's not 
//related to Person for now.
var Customer = function(name) {
    this.name = name;
};

//Now I link the objects and to do so, we link the prototype of Customer to 
//a new instance of Person. The prototype is the base that will be used to 
//construct all new instances and also, will modify dynamically all already 
//constructed objects because in JavaScript objects retain a pointer to the 
//prototype
Customer.prototype = new Person();     

//Now I can call the methods of Person on the Customer, let's try, first 
//I need to create a Customer.
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();

//If I add new methods to Person, they will be added to Customer, but if I
//add new methods to Customer they won't be added to Person. Example:
Customer.prototype.setAmountDue = function(amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
    return this.amountDue;
};

//Let's try:       
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

var Person = function (name) {
    this.name = name;
};
Person.prototype.getName = function () {
    return this.name;
};
var john = new Person("John");
alert(john.getName());
Person.prototype.sayMyName = function () {
    alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function (name) {
    this.name = name;
};
Customer.prototype = new Person();

var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function (amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function () {
    return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

Mientras que como dije no puedo llamar a setAmountDue(), getAmountDue() en una persona.

//The following statement generates an error.
john.setAmountDue(1000);
 1764
Author: stivlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-02 15:03:08

Juego un papel como profesor de JavaScript y el concepto de prototipo siempre ha sido un tema controvertido para cubrir cuando enseño. Me tomó un tiempo llegar a un buen método para aclarar el concepto, y ahora en este texto voy a estar tratando de explicar Cómo hace JavaScript .trabajo de prototipo.


Este es un modelo de objeto basado en un prototipo muy simple que se consideraría como una muestra durante la explicación, sin comentarios aún:

function Person(name){
    this.name = name;
}
Person.prototype.getName = function(){
    console.log(this.name);
}
var person = new Person("George");

Hay algunos puntos cruciales que tenemos que considerar antes de pasar por el concepto de prototipo.

1 - Cómo funcionan realmente las funciones de JavaScript:

Para dar el primer paso tenemos que averiguar, cómo funcionan realmente las funciones de JavaScript, como una clase como función usando this palabra clave en ella o simplemente como una función regular con sus argumentos, lo que hace y lo que devuelve.

Digamos que queremos crear un modelo de objetos Person. pero en este paso voy a estar tratando de haga exactamente lo mismo sin usar prototype y new la palabra clave.

Por Lo tanto en este paso functions, objects y this palabra clave, son todo lo que tenemos.

La primera pregunta sería cómo la palabra clave this podría ser útil sin usar la palabra clave new .

Así que para responder que digamos que tenemos un objeto vacío, y dos funciones como:{[74]]}

var person = {};
function Person(name){  this.name = name;  }

function getName(){
    console.log(this.name);
}

Y ahora sin usar la palabra clave new cómo podríamos usar estos función. Así que JavaScript tiene 3 formas diferentes de hacerlo:

A. La primera forma es llamar a la función como una función regular:

Person("George");
getName();//would print the "George" in the console

En este caso, este sería el objeto de contexto actual, que generalmente es el objeto global window en el navegador o GLOBAL en Node.js. Significa que tendríamos, window.name en el navegador o GLOBAL.name en Nodo.js, con "George" como su valor.

B. Podemos adjuntar a un objeto, como su propiedades

-La forma más fácil de hacer esto es modificar el objeto vacío person, como:

person.Person = Person;
person.getName = getName;

De Esta manera podemos llamarlos como:

person.Person("George");
person.getName();// -->"George"

Y ahora el objeto person es como:

Object {Person: function, getName: function, name: "George"}

-La otra forma de adjuntar una propiedad a un objeto es usando el prototype de ese objeto que se puede encontrar en cualquier objeto JavaScript con el nombre de __proto__, y he tratado de explicarlo un poco en la parte de resumen. Así que podríamos obtener el resultado similar haciendo:

person.__proto__.Person = Person;
person.__proto__.getName = getName;

Pero de esta manera lo que realmente estamos haciendo es modificar el Object.prototype, porque cada vez que creamos un objeto JavaScript usando literales ({ ... }), se crea basado en Object.prototype, lo que significa que se adjunta al objeto recién creado como un atributo llamado __proto__ , así que si lo cambiamos, como hemos hecho en nuestro fragmento de código anterior, todos los objetos JavaScript se cambiarían, no es una buena práctica. Entonces, ¿cuál podría ser la mejor práctica ahora:

person.__proto__ = {
    Person: Person,
    getName: getName
};

Y ahora otros objetos están en paz, pero todavía no parece ser una buena práctica. Así que todavía tenemos una solución más, pero para usar esta solución debemos volver a esa línea de código donde se creó el objeto person (var person = {};) y luego cambiarlo como:

var propertiesObject = {
    Person: Person,
    getName: getName
};
var person = Object.create(propertiesObject);

Lo que hace es crear un nuevo JavaScript Object y adjuntar el propertiesObject al atributo __proto__. Así que para asegurarse de que puede hacer:

console.log(person.__proto__===propertiesObject); //true

Pero el punto complicado aquí es que tienes acceso a todos los propiedades definidas en __proto__ en el primer nivel del objeto person (lea la parte resumen para más detalles).


Como ves, usar cualquiera de estas dos vías this apuntaría exactamente al objeto person.

C. JavaScript tiene otra forma de proporcionar a la función this, que es usar call o apply para invocar la función.

El método apply () llama a una función con un valor dado y argumentos proporcionados como una matriz (o un objeto similar a una matriz).

Y

El método call () llama a una función con un valor dado y argumentos presentados individualmente.

De esta manera, que es mi favorita, podemos llamar fácilmente a nuestras funciones como: {[74]]}

Person.call(person, "George");

O

//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);

getName.call(person);   
getName.apply(person);

Estos 3 métodos son los pasos iniciales importantes para averiguar el .funcionalidad del prototipo.


2 - ¿Cómo funciona la palabra clave new?

Este es el segundo paso para comprender la funcionalidad .prototype.esto es lo que uso para simular el proceso:

function Person(name){  this.name = name;  }
my_person_prototype = { getName: function(){ console.log(this.name); } };

En esta parte voy a estar tratando de tomar todos los pasos que JavaScript toma, sin usar la palabra clave new y prototype, cuando se utiliza la palabra clave new. así que cuando lo hacemos new Person("George"), Person función sirve como constructor, esto es lo que hace JavaScript, uno por uno:

A. en primer lugar hace un objeto vacío, básicamente un hash vacío como:

var newObject = {};

B. el siguiente paso que JavaScript toma es adjuntar todos los objetos prototipo al objeto recién creado

Tenemos my_person_prototype aquí similar al objeto prototipo.

for(var key in my_person_prototype){
    newObject[key] = my_person_prototype[key];
}

No es la forma en que JavaScript realmente asocia las propiedades que se definen en el prototipo. La forma real está relacionada con el concepto de cadena prototipo.


A. & b. En lugar de estos dos pasos, puede obtener exactamente el mismo resultado haciendo:

var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"

Ahora podemos llamar a la getName función en nuestro my_person_prototype:

newObject.getName();

C. entonces le da ese objeto al constructor,{[110]]}

Podemos hacer esto con nuestra muestra como:

Person.call(newObject, "George");

O

Person.apply(newObject, ["George"]);

Entonces el constructor puede hacer lo que quiera, porque este dentro de ese constructor es el objeto que se acaba de crear.

Ahora el resultado final antes de simular los otros pasos: Objeto {nombre: "George"}


Resumen:

Básicamente, cuando se utiliza el nueva palabra clave en una función, estás llamando a eso y esa función sirve como un constructor, así que cuando dices:

new FunctionName()

JavaScript internamente hace un objeto, un hash vacío y luego le da ese objeto al constructor, entonces el constructor puede hacer lo que quiera, porque este dentro de ese constructor es el objeto que se acaba de crear y luego le da ese objeto por supuesto si no ha utilizado la instrucción return en su función o si ponga un return undefined; al final de su cuerpo de función.

Así que cuando JavaScript va a buscar una propiedad en un objeto, lo primero que hace, es buscarla en ese objeto. Y luego hay una propiedad secreta[[prototype]] que normalmente lo tenemos como __proto__ y esa propiedad es lo que JavaScript mira a continuación. Y cuando mira a través de la __proto__, en la medida en que es de nuevo otro objeto JavaScript, tiene su propio __proto__ atributo, sube y sube hasta llegar al punto en que el siguiente __proto__ es nulo. El punto es el único objeto en JavaScript que su __proto__ el atributo is null es Object.prototype objeto:

console.log(Object.prototype.__proto__===null);//true

Y así es como funciona la herencia en JavaScript.

La cadena de prototipos

En otras palabras, cuando tiene una propiedad prototype en una función y llama a una nueva en ella, después de que JavaScript termine de mirar ese objeto recién creado para las propiedades, irá a buscar la función .prototype y también es posible que este objeto tenga su propio prototipo interno. y así sucesivamente.

 166
Author: Mehran Hatami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-07 15:16:00

prototype te permite hacer clases. si no utiliza prototype entonces se convierte en una estática.

He aquí un breve ejemplo.

var obj = new Object();
obj.test = function() { alert('Hello?'); };

En el caso anterior, tiene prueba de llamada de función estática. Esta función solo puede ser accedida por obj.prueba donde puedes imaginar que obj es una clase.

Donde, como en el siguiente código

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

El obj se ha convertido en una clase que ahora puede ser instanciada. Pueden existir varias instancias de obj y todas tienen la función test.

Lo anterior es lo que entiendo. Lo estoy convirtiendo en un wiki comunitario, para que la gente pueda corregirme si me equivoco.

 70
Author: Ramesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 13:51:26

Después de leer este hilo, me siento confundido con JavaScript Prototype Chain, entonces encontré estos gráficos

Http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance * [[protytype]] * y prototype propiedad de objetos de función

es un gráfico claro para mostrar la herencia de JavaScript por Cadena de prototipos

Y

Http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/

este contiene un ejemplo con código y varios diagrama.

La cadena de prototipos finalmente vuelve al Objeto.prototipo.

La cadena de prototipos se puede extender técnicamente el tiempo que desee, cada vez estableciendo el prototipo de la subclase igual a un objeto de la clase padre.

Espero que también te sea útil entender la Cadena de prototipos de JavaScript.

 62
Author: rockXrock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-27 01:33:12

Los siete Koans de prototipo

Mientras Ciro San descendía del Monte Zorro de Fuego después de una profunda meditación, su mente estaba clara y pacífica.

Su mano, sin embargo, estaba inquieta, y por sí misma agarró un pincel y anotó las siguientes notas.


0) Dos cosas diferentes se pueden llamar "prototipo":

  • La propiedad prototype, como en obj.prototype

  • La propiedad interna del prototipo, denotada como [[Prototype]] en ES5 .

    Se puede recuperar a través de la ES5 Object.getPrototypeOf().

    Firefox lo hace accesible a través de la propiedad __proto__ como una extensión. ES6 ahora menciona algunos requisitos opcionales para __proto__.


1) Esos conceptos existen para responder a la pregunta:

Cuando hago obj.property, ¿dónde busca JS .property?

Intuitivamente, la herencia clásica debería afectar la propiedad buscar.


2)

  • __proto__ se utiliza para la búsqueda de propiedades dot . como en obj.property.
  • .prototypees no utilizado para la búsqueda directa, solo indirectamente, ya que determina __proto__ en la creación del objeto con new.

El orden de búsqueda es:

  • obj propiedades añadidas con obj.p = ... o Object.defineProperty(obj, ...)
  • propiedades de obj.__proto__
  • propiedades de obj.__proto__.__proto__, y así sucesivamente
  • si algún __proto__ es null, devuelve undefined.

Esta es la llamada cadena de prototipos .

Puede evitar . búsqueda con obj.hasOwnProperty('key') y Object.getOwnPropertyNames(f)


3) Hay dos formas principales de establecer obj.__proto__:

  • new:

    var F = function() {}
    var f = new F()
    

    Entonces new ha establecido:

    f.__proto__ === F.prototype
    

    Esto es donde .prototype se usa.

  • Object.create:

     f = Object.create(proto)
    

    Conjuntos:

    f.__proto__ === proto
    

4) Las código:

var F = function() {}
var f = new F()

Corresponde al siguiente diagrama:

(Function)       (  F  )                                      (f)
 |  ^             | | ^                                        |
 |  |             | | |                                        |
 |  |             | | +-------------------------+              |
 |  |constructor  | |                           |              |
 |  |             | +--------------+            |              |
 |  |             |                |            |              |
 |  |             |                |            |              |
 |[[Prototype]]   |[[Prototype]]   |prototype   |constructor   |[[Prototype]]
 |  |             |                |            |              |
 |  |             |                |            |              |
 |  |             |                | +----------+              |
 |  |             |                | |                         |
 |  |             |                | | +-----------------------+
 |  |             |                | | |
 v  |             v                v | v
(Function.prototype)              (F.prototype)
 |                                 |
 |                                 |
 |[[Prototype]]                    |[[Prototype]]
 |                                 |
 |                                 |
 | +-------------------------------+
 | |
 v v
(Object.prototype)
 | | ^
 | | |
 | | +---------------------------+
 | |                             |
 | +--------------+              |
 |                |              |
 |                |              |
 |[[Prototype]]   |constructor   |prototype
 |                |              |
 |                |              |
 |                | -------------+
 |                | |
 v                v |
(null)           (Object)

Este diagrama muestra muchos nodos objeto predefinidos de lenguaje: null, Object, Object.prototype, Function y Function.prototype. Nuestras 2 líneas de código solo se crearon f, F y F.prototype.


5) .constructor normalmente viene de F.prototype a través de la búsqueda .:

f.constructor === F
!f.hasOwnProperty('constructor')
Object.getPrototypeOf(f) === F.prototype
F.prototype.hasOwnProperty('constructor')
F.prototype.constructor === f.constructor

Cuando escribimos f.constructor, JavaScript hace la búsqueda . como:

  • f no tiene .constructor
  • f.__proto__ === F.prototype ha .constructor === F, así que tómalo{[79]]}

El resultado f.constructor == F es intuitivamente correcto, ya que F se usa para construir f, por ejemplo, campos establecidos, al igual que en los lenguajes de programación orientada a objetos clásicos.


6) La sintaxis de herencia clásica se puede lograr manipulando cadenas de prototipos.

ES6 agrega las palabras clave class y extends, que son simplemente azúcar de sintaxis para la manipulación de prototipos previamente posible locura.

class C {
    constructor(i) {
        this.i = i
    }
    inc() {
        return this.i + 1
    }
}

class D extends C {
    constructor(i) {
        super(i)
    }
    inc2() {
        return this.i + 2
    }
}
// Inheritance syntax works as expected.
(new C(1)).inc() === 2
(new D(1)).inc() === 2
(new D(1)).inc2() === 3
// "Classes" are just function objects.
C.constructor === Function
C.__proto__ === Function.prototype
D.constructor === Function
// D is a function "indirectly" through the chain.
D.__proto__ === C
D.__proto__.__proto__ === Function.prototype
// "extends" sets up the prototype chain so that base class
// lookups will work as expected
var d = new D(1)
d.__proto__ === D.prototype
D.prototype.__proto__ === C.prototype
// This is what `d.inc` actually does.
d.__proto__.__proto__.inc === C.prototype.inc
// Class variables
// No ES6 syntax sugar apparently:
// http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives
C.c = 1
C.c === 1
// Because `D.__proto__ === C`.
D.c === 1
// Nothing makes this work.
d.c === undefined

Diagrama simplificado sin todos los objetos predefinidos:

      __proto__
(C)<---------------(D)         (d)
| |                |           |
| |                |           |
| |prototype       |prototype  |__proto__
| |                |           |
| |                |           |
| |                | +---------+
| |                | |
| |                | |
| |                v v
|__proto__        (D.prototype)
| |                |
| |                |
| |                |__proto__
| |                |
| |                |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)--->(inc)
|
v
Function.prototype
 61
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-08 06:31:36

Cada objeto tiene una propiedad interna, [[Prototype]], vincular a otro objeto:

object [[Prototype]] -> anotherObject

En javascript tradicional, el objeto vinculado es la propiedad prototype de una función:

object [[Prototype]] -> aFunction.prototype

Algunos entornos exponen [[Prototipo]] como __proto__:

anObject.__proto__ === anotherObject

Se crea el enlace [[Prototype]] al crear un objeto.

// (1) Object.create:
var object = Object.create(anotherObject)
// object.__proto__ = anotherObject

// (2) ES6 object initializer:
var object = { __proto__: anotherObject };
// object.__proto__ = anotherObject

// (3) Traditional JavaScript:
var object = new aFunction;
// object.__proto__ = aFunction.prototype

Así que estas declaraciones son equivalentes:

var object = Object.create(Object.prototype);
var object = { __proto__: Object.prototype }; // ES6 only
var object = new Object;

Una instrucción new no muestra el destino del enlace (Object.prototype) en sí; en lugar de el objetivo está implícito en el constructor (Object).

Recuerda:

  • Cada objeto tiene un enlace, [[Prototipo]], a veces expuesto como __proto__.
  • Cada función tiene una propiedad prototype.
  • Los objetos creados con new están vinculados a la propiedad prototype de su constructor.
  • Si una función nunca se usa como constructor, su propiedad prototype no se usará.
  • Si no necesita un constructor, utilice el objeto .crear en lugar de new.
 35
Author: sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 19:32:32

Javascript no tiene herencia en el sentido habitual, pero tiene la cadena de prototipos.

Cadena de prototipos

Si un miembro de un objeto no se puede encontrar en el objeto, lo busca en la cadena de prototipos. La cadena se compone de otros objetos. Se puede acceder al prototipo de una instancia dada con la variable __proto__. Cada objeto tiene uno, ya que no hay diferencia entre clases e instancias en javascript.

La ventaja de añadir una función / variable a la el prototipo es que tiene que estar en la memoria solo una vez, no para cada instancia.

También es útil para la herencia, porque la cadena de prototipos puede consistir en muchos otros objetos.

 24
Author: Georg Schölly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 12:41:31

Este artículo es largo. Pero estoy seguro de que aclarará la mayoría de sus preguntas en cuanto a la naturaleza "prototípica" de la Herencia de JavaScript. Y aún más. Por favor lea el artículo completo.

JavaScript básicamente tiene dos tipos de tipos de datos

  • No objetos
  • Objetos

No objetos

Los siguientes son los No objeto datos tipos

  • string
  • número (incluyendo NaN e Infinito)
  • valores booleanos (true,false)
  • undefined

Estos tipos de datos regresan después cuando se utiliza el operador typeof

Tipo de "string literal" (o una variable que contiene string literal) === 'string'

Typeof 5 (o cualquier literal numérico, o un variable que contiene literal numérico, o NaN o Infynity) === 'número'

Typeof true (o false o una variable que contenga true o false) === 'boolean'

Typeof indefinido (o una variable no definida o una variable que contenga indefinido) === 'undefined'

El cadena,número y los tipos de datos booleanos se pueden representar tanto como Objetos y No objetos.Cuando son representados como objetos su typeof es siempre = = = 'object'. Volveremos a esto una vez que entendamos los tipos de datos del objeto.

Objetos

Los tipos de datos de los objetos se pueden dividir en dos tipos

  1. Tipo de función objects
  2. Objetos de tipo no funcional

El Los objetos de tipo de función son los que devuelven la cadena 'function'con el operador typeof. Todas las funciones definidas por el usuario y todos los objetos integrados en JavaScript que pueden crear nuevos objetos mediante el uso de nuevo operador caen en esta categoría. Por ejemplo.

  • Objeto
  • String
  • Número
  • Boolean
  • Array
  • Mecanografiado Arrays
  • RegExp
  • Función
  • Todos los demás objetos incorporados que pueden crear nuevos objetos mediante el uso de nuevo operador
  • función Función definida por el usuario(){ /*código definido por el usuario*/}

So, typeof(Objeto) === typeof(String) === typeof(Número de) === typeof(Boolean) === typeof(Matriz) === typeof(RegExp) === typeof(Function) === typeof(UserDefinedFunction) === 'la función'

Todos los Tipo de función objetos son realmente instancias del objeto JavaScript construido Function (incluyendo el objeto Function es decir, está definido recursivamente). Es como si estos objetos se han definido de la siguiente manera

var Object= new Function ([native code for object Object])
var String= new Function ([native code for object String])
var Number= new Function ([native code for object Number])
var Boolean= new Function ([native code for object Boolean])
var Array= new Function ([native code for object Array])
var RegExp= new Function ([native code for object RegExp])
var Function= new Function ([native code  for object Function])
var UserDefinedFunction= new Function ("user defined code")

Como se mencionó, el Tipo de función objetos puede crear más nuevos objetos que usan el nuevo operador . Para el correo.g un objeto de tipo Objeto, Cadena, Número de, Boolean, Matriz, RegExp O UserDefinedFunction puede ser creado usando

var a=new Object() or var a=Object() or var a={} //Create object of type Object
var a=new String() //Create object of type String
var a=new Number() //Create object of type Number
var a=new Boolean() //Create object of type Boolean
var a=new Array() or var a=Array() or var a=[]  //Create object of type Array
var a=new RegExp() or var a=RegExp() //Create object of type RegExp
var a=new UserDefinedFunction() 

Los objetos así creados son todos Objetos de tipo no funcional y devolver su tipo de==='objeto' . En todos estos casos, el objeto "a" no puede crear objetos usando el operador nuevo. Así que lo siguiente está mal

var b=new a() //error. a is not typeof==='function'

El construido en El objeto Math es typeof==='el objeto'. Por lo tanto, un nuevo objeto de tipo Math no puede ser creado por un nuevo operador.

var b=new Math() //error. Math is not typeof==='function'

También observe que Objeta,Las funciones Array y RegExp pueden crear un nuevo objeto sin siquiera usar el operador new. Sin embargo, los siguientes no lo hacen.

var a=String() // Create a new Non Object string. returns a typeof==='string' 
var a=Number() // Create a new Non Object Number. returns a typeof==='number'
var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'

Las funciones definidas por el usuario son casos especiales.

var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.

Desde las Tipo de función objetos puede crear nuevos objetos que también se llaman Constructoras.

Cada Constructor/Función (ya sea construido o definido por el usuario) cuando se define automáticamente tiene una propiedad llamada "prototype" cuyo valor por defecto se establece como un objeto. Este objeto tiene una propiedad llamada "constructor" que, por defecto, referencias a la Constructor/Función .

Para ejemplo, cuando definimos una función

function UserDefinedFunction()
{
}

Lo siguiente sucede automáticamente

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

Esta propiedad "prototype" solo está presente en los objetos de tipo de función (y nunca en Objetos de tipo no función).

Esto se debe a que cuando se crea un nuevo objeto (utilizando un operador nuevo)hereda todas las propiedades y métodos del objeto prototipo actual de la función Constructora, es decir, un referencia interna es creado en el objeto recién creado que hace referencia al objeto referenciado por el objeto prototipo actual de la función Constructor.

Esta "referencia interna" que se crea en el objeto para hacer referencia a propiedades heredadas se conoce como el prototipo del objeto (que hace referencia al objeto al que hace referencia la propiedad del Constructor "prototipo" pero es diferente de ella). Para cualquier objeto (Función o No Función) esto se puede recuperar usando Objeto.Método getPrototypeOf () . Usando este método uno puede rastrear la cadena prototipo de un objeto.

También, cada objeto que se crea (Function type o Non Function type) tiene una propiedad "constructor" que se hereda del objeto referenciado por la propiedad prototype de la función Constructora. Por defecto esta propiedad "constructor" hace referencia a la función Constructor que la creó (si la El "prototipo" predeterminado de la función Constructor no se cambia).

Para todos Tipo de función objetos la función constructor es siempre función Función(){}

Para Objetos de tipo no funcional (ej., Javascript Construido en el objeto Math) la función constructora es la función que la creó. Para Math objeto es Objeto de la función(){}.

Todo el concepto explicado anteriormente puede ser un poco desalentador de entender sin ningún código de apoyo. Por favor, vaya a través del siguiente código línea por línea para entender el concepto. Trate de ejecutarlo para tener una mejor comprensión.

function UserDefinedFunction()
{ 

} 

/* creating the above function automatically does the following as mentioned earlier

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

*/


var newObj_1=new UserDefinedFunction()

alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays true

alert(newObj_1.constructor) //Displays function UserDefinedFunction

//Create a new property in UserDefinedFunction.prototype object

UserDefinedFunction.prototype.TestProperty="test"

alert(newObj_1.TestProperty) //Displays "test"

alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test"

//Create a new Object

var objA = {
        property1 : "Property1",
        constructor:Array

}


//assign a new object to UserDefinedFunction.prototype
UserDefinedFunction.prototype=objA

alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays false. The object referenced by UserDefinedFunction.prototype has changed

//The internal reference does not change
alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction

alert(newObj_1.TestProperty) //This shall still Display "test" 

alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test"


//Create another object of type UserDefinedFunction
var newObj_2= new UserDefinedFunction();

alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true.

alert(newObj_2.constructor) //Displays function Array()

alert(newObj_2.property1) //Displays "Property1"

alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1"

//Create a new property in objA
objA.property2="property2"

alert(objA.property2) //Displays "Property2"

alert(UserDefinedFunction.prototype.property2) //Displays "Property2"

alert(newObj_2.property2) // Displays Property2

alert(Object.getPrototypeOf(newObj_2).property2) //Displays  "Property2"

La cadena prototipo de cada objeto en última instancia se remonta al Objeto.prototipo (que a su vez no tiene ningún objeto prototipo) . El siguiente código se puede utilizar para trazar la cadena prototipo de un objeto

var o=Starting object;

do {
    alert(o + "\n" + Object.getOwnPropertyNames(o))

}while(o=Object.getPrototypeOf(o))

La cadena de prototipos para varios objetos funciona fuera como sigue.

  • Cada objeto de función (incluido el objeto de función incorporado) -> Función.prototipo - > Objeto.prototype - > null
  • Objetos simples (creados por new Object() o {} incluyendo built in Math object)-> Object.prototype - > null
  • Objeto creado con new or Object.create - > One or More prototype chains - > Object.prototype - > null

Para crear un objeto sin ningún prototipo use lo siguiente:

var o=Object.create(null)
alert(Object.getPrototypeOf(o)) //Displays null

Uno podría piense que establecer la propiedad prototype del Constructor a null creará un objeto con un prototipo nulo. Sin embargo, en tales casos, el prototipo del objeto recién creado se establece en Objeto.prototype y su constructor se establece en function Object. Esto se demuestra mediante el siguiente código

function UserDefinedFunction(){}
UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.)

var o=new UserDefinedFunction()
alert(Object.getPrototypeOf(o)==Object.prototype)   //Displays true
alert(o.constructor)    //Displays Function Object

Siguiente en el resumen de este artículo

  • Hay dos tipos de objetos tipos de Función y No tipos de Función
  • Only Tipo de función objects puede crear un nuevo objeto usando el operador new. Los objetos así creados son objetos no de tipo función. Los objetos que no son de tipo Función no pueden crear un objeto usando el operador new.

  • Todos los objetos de tipo función por defecto tienen una propiedad "prototype". Esta propiedad "prototype" hace referencia a un objeto que tiene una propiedad "constructor" que por default hace referencia al tipo de función object en sí.

  • Todos los objetos ( Function type y Non Function type ) tienen una propiedad "constructor" que por defecto hace referencia al objeto de tipo de función /Constructor que lo creó.

  • Cada objeto que se crea internamente hace referencia al objeto referenciado por "prototype" propiedad del Constructor que lo creó. Este objeto se conoce como el creado prototipo del objeto (que es diferente de la propiedad Function type objects "prototype" a la que hace referencia) . De esta manera, el objeto creado puede acceder directamente a los métodos y propiedades definidos en el objeto referenciado por la propiedad "prototype" del Constructor (en el momento de la creación del objeto).

  • El prototipo de un objeto (y por lo tanto sus nombres de propiedad heredados) se puede recuperar usando el Objeto .Método getPrototypeOf () . En hecho este método se puede utilizar para navegar por toda la cadena de prototipos del objeto.

  • La cadena prototipo de cada objeto en última instancia se remonta al Objeto.prototype (A menos que el objeto se cree usando Object.crear (null) en cuyo caso el objeto no tiene prototipo).

  • Typeof (new Array ()) = = = 'object' es por diseño de lenguaje y no un error como señala Douglas Crockford

  • Configuración del prototipo la propiedad del Constructor a null (or undefined,number,true,false,string) no creará un objeto con un prototipo nulo. En tales casos, el prototipo del objeto recién creado se establece en Objeto.prototype y su constructor se establece en function Object.

Espero que esto ayude.

 24
Author: Arup Hore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-14 05:09:30

El concepto de prototypal herencia es uno de los más complicados para muchos desarrolladores. Vamos a tratar de entender la raíz del problema para entender prototypal inheritance mejor. Comencemos con una función plain.

introduzca la descripción de la imagen aquí

Si usamos un operador new en el Tree function, lo llamamos como una función constructor.

introduzca la descripción de la imagen aquí

Cada función JavaScript tiene un prototype. Cuando se registra el Tree.prototype, se conseguir...

introduzca la descripción de la imagen aquí

Si miras la salida anterior console.log(), podrías ver una propiedad constructor en Tree.prototype y una propiedad __proto__ también. El __proto__ representa el prototype que este function se basa, y ya que esto es solo un JavaScript function simple sin inheritance configurado todavía, se refiere al Object prototype que es algo construido para JavaScript...

Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Esto tiene cosas como .toString, .toValue, .hasOwnProperty etc...

__proto__ que se trajo mi mozilla está en desuso y se sustituye por Object.getPrototypeOf método para obtener el object's prototype.

introduzca la descripción de la imagen aquí

Object.getPrototypeOf(Tree.prototype); // Object {} 

Vamos a añadir un método a nuestra Tree prototype.

introduzca la descripción de la imagen aquí

Hemos modificado el Root y añadido a function branch to it.

introduzca la descripción de la imagen aquí

Eso significa que cuando creas un instance de Tree, puedes llamarlo su método branch.

introduzca la descripción de la imagen aquí

También podemos añadir primitives o objects a nuestro Prototype.

introduzca la descripción de la imagen aquí

Vamos a añadir un child-tree a nuestro Tree.

introduzca la descripción de la imagen aquí

Aquí el Child hereda su prototype del Árbol, lo que estamos haciendo aquí es usar el método Object.create() para crear un nuevo objeto basado en lo que pasa, aquí está Tree.prototype. En este caso lo que estamos haciendo es establecer el prototipo de Hijo a un nuevo objeto que se ve idéntico al prototipo Tree. A continuación estamos configurando el Child's constructor to Child, si no lo hacemos apuntaría a Tree().

introduzca la descripción de la imagen aquí

Child ahora tiene su propio prototype, sus __proto__ puntos a Tree y Tree's prototype puntos a base Object.

Child  
|
 \
  \
   Tree.prototype
   - branch
   |
   |
    \
     \
      Object.prototype
      -toString
      -valueOf
      -etc., etc.

Ahora se crea un instance de Child y se llama branch que es originalmente disponible en Tree. En realidad no hemos definido nuestro branch en el Child prototype. PERO, en el Root prototype de qué Hijo hereda.

introduzca la descripción de la imagen aquí

En JS todo no es un objeto, todo puede actuar como un objeto.

Javascript tiene primitivos como strings, number, booleans, undefined, null. No son object(i.e reference types), pero ciertamente pueden actuar como un object. Veamos un ejemplo aquí.

introduzca la descripción de la imagen aquí

En la primera línea de este listado, un primitive el valor de la cadena se asigna al nombre. La segunda línea trata el nombre como un object y llama a charAt(0) usando la notación de puntos.

Esto es lo que sucede entre bastidores: // lo que hace el motor JavaScript

introduzca la descripción de la imagen aquí

La String object existe solo para una declaración antes de ser destruida (un proceso llamado autoboxing). Volvamos a nuestra prototypal inheritance.

  • Javascript soporta la herencia a través de delegation basado en prototypes.
  • Cada Function tiene un prototype propiedad, que se refiere a otro objeto.
  • properties/functions se miran desde el object mismo o vía prototype cadena si no existe

A prototype en JS es un objeto que yields usted al padre de otro object. [ie.. delegación] Delegation significa que si no puedes hacer algo, le dirás a otra persona que lo haga por ti.

introduzca la descripción de la imagen aquí

Https://jsfiddle.net/say0tzpL/1 /

Si miras hasta el violín anterior, dog tiene acceso al método toString, pero no está disponible en él, pero está disponible a través de la cadena de prototipos que delega a Object.prototype

introduzca la descripción de la imagen aquí

Si nos fijamos en el siguiente, estamos tratando de acceder al método call que está disponible en cada function.

introduzca la descripción de la imagen aquí

Https://jsfiddle.net/rknffckc /

Si busca el violín anterior, la función Profile tiene acceso al método call , pero no está disponible en él, pero está disponible a través de la cadena de prototipos que delega a Function.prototype

introduzca la descripción de la imagen aquí

Nota: prototype es una propiedad del constructor de la función, mientras que __proto__ es una propiedad de los objetos construidos a partir del constructor de la función. Cada función viene con una propiedad prototype cuyo valor es un object vacío. Cuando creamos una instancia de la función, obtenemos una propiedad interna [[Prototype]] o __proto__, cuya referencia es el prototipo de la Función constructor.

introduzca la descripción de la imagen aquí

El diagrama anterior parece un poco complicado, pero muestra el panorama completo de cómo funciona prototype chaining. Vamos a caminar a través de esto lentamente:

Hay dos instancias b1 y b2, cuyo constructor es Bar y padre es Foo y tiene dos métodos de prototype chain identify y speak vía Bar y Foo

introduzca la descripción de la imagen aquí

Https://jsfiddle.net/kbp7jr7n /

Si busca el código anterior, tenemos Foo constructor que tiene el método identify() y Bar constructor que tiene el método speak. Creamos dos Bar instancia b1 y b2 cuyo tipo padre es Foo. Ahora, mientras se llama speak método de Bar, somos capaces de identificar el que está llamando a hablar a través de la cadena prototype.

introduzca la descripción de la imagen aquí

Bar ahora tiene todos los métodos de Foo que se definen en su prototype. Profundicemos más en la comprensión de Object.prototype y Function.prototype y cómo están relacionados. Si buscas el constructor de Foo, Bar y Object son Function constructor.

introduzca la descripción de la imagen aquí

El prototype de Bar es Foo, prototype de Foo es Object y si usted mira de cerca el prototype de Foo está relacionado con Object.prototype.

introduzca la descripción de la imagen aquí

Antes de cerrar esto, vamos a envolver con un pequeño trozo de código aquí para resumir todo lo anterior. Estamos usando el operador instanceof aquí para comprobar si un object tiene en su cadena prototype la propiedad prototype de un constructor que a continuación resume todo el diagrama grande.

introduzca la descripción de la imagen aquí

Espero que este add sea algo de información, sé que esto podría ser grande de entender... en palabras simples su ¡son solo objetos vinculados a objetos!!!!

 20
Author: Thalaivar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-03 21:44:50

¿Cuál es el propósito exacto de esto ".prototype " propiedad?

La interfaz a las clases estándar se vuelve extensible. Por ejemplo, está utilizando la clase Array y también necesita agregar un serializador personalizado para todos sus objetos de matriz. Pasarías tiempo codificando una subclase, o usarías composición o ... La propiedad prototype resuelve esto permitiendo a los usuarios controlar el conjunto exacto de miembros/métodos disponibles para una clase.

Piense en los prototipos como un extra vtable-puntero. Cuando faltan algunos miembros de la clase original, el prototipo se busca en tiempo de ejecución.

 19
Author: dirkgently,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 12:37:38

Puede ser útil categorizar las cadenas de prototipos en dos categorías.

Considere el constructor:

 function Person() {}

El valor de Object.getPrototypeOf(Person) es una función. De hecho, es Function.prototype. Dado que Person fue creado como una función, comparte el mismo objeto de función prototipo que todas las funciones tienen. Es lo mismo que Person.__proto__, pero esa propiedad no debe ser usada. De todos modos, con Object.getPrototypeOf(Person) efectivamente subes la escalera de lo que se llama la cadena prototipo.

La cadena en dirección hacia arriba se ve así:

PersonFunction.prototypeObject.prototype (punto final)

Importante es que esta cadena prototipo tiene poco que ver con los objetos que Personpueden construir. Esos objetos construidos tienen su propia cadena prototipo, y esta cadena potencialmente no puede tener un ancestro cercano en común con la mencionada anteriormente.

Tomemos por ejemplo este objeto:

var p = new Person();

p no tiene relación directa prototipo-cadena con Persona. Su la relación es diferente. El objeto p tiene su propia cadena prototipo. Usando Object.getPrototypeOf, encontrarás que la cadena es la siguiente:

pPerson.prototypeObject.prototype (punto final)

No hay ningún objeto de función en esta cadena (aunque eso podría ser).

Así que Person parece estar relacionado con dos tipos de cadenas, que viven sus propias vidas. Para" saltar " de una cadena a la otra, se usa:

  1. .prototype: saltar de la cadena del constructor a la creado-cadena del objeto. Por lo tanto, esta propiedad solo se define para objetos de función (ya que new solo se puede usar en funciones).

  2. .constructor: salta de la cadena del objeto creado a la cadena del constructor.

Aquí hay una presentación visual de las dos cadenas prototipo involucradas, representadas como columnas: {[43]]}

introduzca la descripción de la imagen aquí

Para resumir:

La propiedad prototype no proporciona información del prototipo del sujeto cadena, sino de objetos creados por el sujeto.

No es de extrañar que el nombre de la propiedad prototype pueda llevar a confusión. Tal vez habría sido más claro si esta propiedad se hubiera nombrado prototypeOfConstructedInstances o algo en esa línea.

Puedes saltar de un lado a otro entre las dos cadenas de prototipos:{[43]]}

Person.prototype.constructor === Person

Esta simetría se puede romper asignando explícitamente un objeto diferente a la propiedad prototype (más sobre esto más adelante).

Crear uno Función, Obtener Dos Objetos

Person.prototype es un objeto que se creó al mismo tiempo que se creó la función Person. Tiene Person como constructor, a pesar de que ese constructor no se ejecutó todavía. Así que se crean dos objetos al mismo tiempo:

  1. La función Person en sí
  2. El objeto que actuará como prototipo cuando se llame a la función como constructor

Ambos son objetos, pero tienen diferentes roles: el objeto función construye, mientras que el otro objeto representa el prototipo de cualquier objeto que la función construirá. El objeto prototipo se convertirá en el padre del objeto construido en su cadena prototipo.

Dado que una función también es un objeto, también tiene su propio padre en su propia cadena prototipo, pero recuerde que estas dos cadenas son sobre cosas diferentes.

Aquí hay algunas igualdades que podrían ayudar a comprender el problema all true:

function Person() {};

// This is prototype chain info for the constructor (the function object):
console.log(Object.getPrototypeOf(Person) === Function.prototype);
// Step further up in the same hierarchy:
console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype);
console.log(Object.getPrototypeOf(Object.prototype) === null);
console.log(Person.__proto__ === Function.prototype);
// Here we swap lanes, and look at the constructor of the constructor
console.log(Person.constructor === Function);
console.log(Person instanceof Function);

// Person.prototype was created by Person (at the time of its creation)
// Here we swap lanes back and forth:
console.log(Person.prototype.constructor === Person);
// Although it is not an instance of it:
console.log(!(Person.prototype instanceof Person));
// Instances are objects created by the constructor:
var p = new Person();
// Similarly to what was shown for the constructor, here we have
// the same for the object created by the constructor:
console.log(Object.getPrototypeOf(p) === Person.prototype);
console.log(p.__proto__ === Person.prototype);
// Here we swap lanes, and look at the constructor
console.log(p.constructor === Person);
console.log(p instanceof Person);

Añadiendo niveles a la cadena de prototipos

Aunque se crea un objeto prototipo cuando se crea una función de constructor, puede ignorar ese objeto y asignar otro objeto que se debe usar como prototipo para cualquier instancia posterior creada por ese constructor.

Por ejemplo:

function Thief() { }
var p = new Person();
Thief.prototype = p; // this determines the prototype for any new Thief objects:
var t = new Thief();

Ahora la cadena prototipo de t es un paso más largo que el de p :

    tpPerson.prototypeObject.prototype (punto final)

La otra cadena de prototipos ya no es: Thief y {[7] } son hermanos que comparten el mismo padre en su cadena de prototipos:

    Person}
    Thief } → Function.prototypeObject.prototype (punto final)

El gráfico presentado anteriormente se puede extender a esto (el original Thief.prototype se omite):

introduzca la descripción de la imagen aquí

Las líneas azules representan cadenas prototipo, las otras líneas coloreadas representan otras relaciones:

  • entre un objeto y su constructor
  • entre un constructor y el objeto prototipo que se utilizará para construir objetos
 17
Author: trincot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-22 20:59:37

La Guía Definitiva para JavaScript Orientado a objetos - una explicación de video muy concisa y clara de ~30 minutos de la pregunta formulada (El tema de la Herencia prototípica comienza desde 5:45, aunque prefiero escuchar todo el video). El autor de este video también hizo JavaScript object visualizer sitio web http://www.objectplayground.com/.introduzca la descripción de la imagen aquí introduzca la descripción de la imagen aquí

 16
Author: Bad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-18 17:30:56

Me pareció útil explicar la" cadena de prototipos " como convención recursiva cuando se hace referencia a obj_n.prop_X:

Si obj_n.prop_X no existe, marque obj_n+1.prop_X donde obj_n+1 = obj_n.[[prototype]]

Si el prop_X finalmente se encuentra en el objeto prototipo k-ésimo entonces

obj_1.prop_X = obj_1.[[prototype]].[[prototype]]..(k-times)..[[prototype]].prop_X

Puede encontrar un gráfico de la relación de los objetos Javascript por sus propiedades aquí:

gráfico de objetos js

Http://jsobjects.org

 13
Author: B M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-09 11:45:44

Cuando un constructor crea un objeto, ese objeto hace referencia implícitamente a la propiedad "prototype" del constructor con el propósito de resolver referencias de propiedades. La propiedad "prototype" del constructor puede ser referenciada por el constructor de expresiones del programa.el prototipo y las propiedades agregadas al prototipo de un objeto son compartidas, a través de herencia, por todos los objetos que comparten el prototipo.

 12
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-05 18:42:10

Permítanme decirles mi comprensión de los prototipos. No voy a comparar la herencia aquí con otros idiomas. Me gustaría que la gente dejara de comparar idiomas, y solo entendiera el idioma como sí mismo. Entender los prototipos y la herencia prototípica es tan simple, como te mostraré a continuación.

Prototype es como un modelo, basado en el cual se crea un producto. El punto crucial a entender es que cuando se crea un objeto usando otro objeto como prototipo, el enlace entre el prototipo y el producto es siempre duradero. Por ejemplo:

var model = {x:2};
var product = Object.create(model);
model.y = 5;
product.y
=>5

Cada objeto contiene una propiedad interna llamada [[prototype]], a la que puede acceder la función Object.getPrototypeOf(). Object.create(model) crea un nuevo objeto y establece su propiedad [[prototype]] en el modelo object . Por lo tanto, cuando lo haga Object.getPrototypeOf(product), obtendrá el objeto modelo.

Las propiedades en el producto se manejan de la siguiente manera:

  • Cuando se accede a una propiedad acaba de leer su valor, su miró hacia arriba en la cadena de alcance. La búsqueda de la variable comienza desde el producto hacia arriba hasta su prototipo. Si se encuentra una variable de este tipo en la búsqueda, la búsqueda se detiene allí mismo y se devuelve el valor. Si no se puede encontrar una variable de este tipo en la cadena de ámbito, se devuelve undefined.
  • Cuando se escribe una propiedad(alterada), entonces la propiedad siempre se escribe en el objeto product. Si el producto no tiene propiedad ya, está implícitamente creado y escrito.

Tal vinculación de objetos utilizando el prototipo de la propiedad se denomina prototípico de la herencia. Ahí, es tan simple, ¿de acuerdo?

 9
Author: Aravind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-09 15:59:28

Considere el siguiente keyValueStore objeto:

var keyValueStore = (function() {
    var count = 0;
    var kvs = function() {
        count++;
        this.data = {};
        this.get = function(key) { return this.data[key]; };
        this.set = function(key, value) { this.data[key] = value; };
        this.delete = function(key) { delete this.data[key]; };
        this.getLength = function() {
            var l = 0;
            for (p in this.data) l++;
            return l;
        }
    };

    return  { // Singleton public properties
        'create' : function() { return new kvs(); },
        'count' : function() { return count; }
    };
})();

Puedo crear una nueva instancia de este objeto haciendo esto :

kvs = keyValueStore.create();

Cada instancia de este objeto tendría las siguientes propiedades públicas:

  • data
  • get
  • set
  • delete
  • getLength

Ahora, supongamos que creamos 100 instancias de este objeto keyValueStore. Aunque get, set, delete, getLength hará exactamente lo mismo para cada una de estas 100 instancias, cada instancia tiene su propia copia de esta función.

Ahora, imagina si pudieras tener un solo get, set, delete y getLength copiar, y cada instancia haría referencia a esa misma función. Esto sería mejor para el rendimiento y requiere menos memoria.

Ahí es donde entran los prototipos. Un prototipo es un "blueprint" de propiedades que se hereda pero no se copia por instancias. Esto significa que solo existe una vez en la memoria para todas las instancias de un objeto y es compartida por todos de esos casos.

Ahora, considere el objeto keyValueStore de nuevo. Podría reescribirlo así:

var keyValueStore = (function() {
    var count = 0;
    var kvs = function() {
        count++;
        this.data = {};
    };

    kvs.prototype = {
        'get' : function(key) { return this.data[key]; },
        'set' : function(key, value) { this.data[key] = value; },
        'delete' : function(key) { delete this.data[key]; },
        'getLength' : function() {
            var l = 0;
            for (p in this.data) l++;
            return l;
        }
    };

    return  {
        'create' : function() { return new kvs(); },
        'count' : function() { return count; }
    };
})();

Esto hace EXACTAMENTE lo mismo que la versión anterior del objeto keyValueStore, excepto que todos sus métodos ahora se ponen en un prototipo. Lo que esto significa, es que todas las 100 instancias ahora comparten estos cuatro métodos en lugar de tener cada una su propia copia.

 8
Author: John Slegers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-11 19:24:36

Aquí hay dos entidades distintas pero relacionadas que necesitan explicación:{[38]]}

  • La propiedad .prototype de funciones.
  • La [[Prototype]][1] la propiedad de todos los objetos[2].

Estas son dos cosas diferentes.

La propiedad [[Prototype]]:

Esta es una propiedad que existe en todos los[2] objetos.

Lo que se almacena aquí es otro objeto, que, como un objeto en sí, tiene un [[Prototype]] de su propio que apunta a otro objeto. Ese otro objeto tiene un [[Prototype]] propio. Esta historia continúa hasta llegar al objeto prototípico que proporciona métodos que son accesibles en todos los objetos (como .toString).

La propiedad [[Prototype]] es parte de lo que forma la cadena [[Prototype]]. Esta cadena de [[Prototype]] objetos es lo que se examina cuando, por ejemplo, [[Get]] o [[Set]] operaciones se realizan en un objeto:

var obj = {}
obj.a         // [[Get]] consults prototype chain
obj.b = 20    // [[Set]] consults prototype chain

La propiedad .prototype:

Esta es una propiedad eso solo se encuentra en funciones. Usando una función muy simple:

function Bar(){};

La propiedad .prototype contiene un objeto que será asignado a b.[[Prototype]] cuando lo haga var b = new Bar. Usted puede examinar fácilmente esto:

// Both assign Bar.prototype to b1/b2[[Prototype]]
var b = new Bar;
// Object.getPrototypeOf grabs the objects [[Prototype]]
console.log(Object.getPrototypeOf(b) === Bar.prototype) // true

Una de las .prototypes más importantes es la de la función Object . Este prototipo contiene el objeto prototípico que contienen todas las cadenas [[Prototype]]. En él, se definen todos los métodos disponibles para nuevos objetos:

// Get properties that are defined on this object
console.log(Object.getOwnPropertyDescriptors(Object.prototype))

Ahora, ya que .prototype es un objeto, tiene una propiedad [[Prototype]]. Cuando no haces ninguna asignación a Function.prototype, los .prototype's [[Prototype]] apuntan al objeto prototípico (Object.prototype). Esto se realiza automáticamente cada vez que crea una nueva función.

De esta manera, cada vez que lo hagas new Bar; se configura la cadena de prototipos para ti, obtienes todo definido en Bar.prototype y todo definido en Object.prototype:

var b = new Bar;
// Get all Bar.prototype properties
console.log(b.__proto__ === Bar.prototype)
// Get all Object.prototype properties
console.log(b.__proto__.__proto__ === Object.prototype)

Cuando hace {[73] } hacer asignaciones a Function.prototype todo lo que está haciendo es extender la cadena de prototipos para incluir otro objeto. Es como una inserción en una lista ligada sencilla.

Esto básicamente altera la cadena [[Prototype]] permitiendo que las propiedades que se definen en el objeto asignado a Function.prototype sean vistas por cualquier objeto creado por la función.


[1: Eso no confundirá a nadie; disponible a través de la propiedad __proto__ en muchas implementaciones.
[2]: Todos, excepto null.

 8
Author: Jim Fasarakis Hilliard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-03 17:46:58

Otro intento de explicar La herencia basada en prototipos de JavaScript con mejores imágenes

Objetos simples heredados

 7
Author: rus1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-24 21:27:45

Siempre me gustan las analogías cuando se trata de entender este tipo de cosas. 'Herencia prototípica' es bastante confuso en comparación con la herencia de clase bajo en mi opinión, a pesar de que los prototipos son paradigma mucho más simple. De hecho, con los prototipos, realmente no hay herencia, por lo que el nombre en sí mismo engañoso, es más un tipo de 'delegación'.

Imagina esto ....

Estás en la escuela secundaria, y estás en clase y tienes un examen que es debido hoy, pero no tienes un bolígrafo para llenar tus respuestas. Doh!

Estás sentado al lado de tu amigo Finnius, que podría tener un bolígrafo. Le preguntas, y él mira alrededor de su escritorio sin éxito, pero en lugar de decir "No tengo un bolígrafo", es un buen amigo que comprueba con su otro amigo Derp si tiene un bolígrafo. Derp de hecho tiene un bolígrafo de repuesto y se lo pasa a Finnius, quien se lo pasa a usted para completar su prueba. Derp ha confiado la pluma a Finnius, que ha delegado la pluma a usted para su uso.

¿Qué es importante aquí es que Derp no te da la pluma, ya que no tienes una relación directa con él.

Este es un ejemplo simplificado de cómo funcionan los prototipos, donde se busca un árbol de datos para lo que está buscando.

 7
Author: Louis Moore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-09 04:49:52

Resumen:

  • Las funciones son objetos en javascript y por lo tanto pueden tener propiedades
  • (Constructor) las funciones siempre tienen una propiedad prototype
  • Cuando se usa una función como constructor con la palabra clave new el objeto obtiene una propiedad __proto__
  • Esta propiedad __proto__ se refiere a la propiedad prototype de la función constructor.

Ejemplo:

function Person (name) {
  this.name = name;
}

let me = new Person('willem');

console.log(Person.prototype) // Person has a prototype property

console.log(Person.prototype === me.__proto__) // the __proto__ property of the instance refers to prototype property of the function.

¿Por qué es útil esto:

Javascript tiene un mecanismo al buscar propiedades en Objetos que se llama 'herencia prototípica' , esto es lo que básicamente hace:

  • Primero se comprueba si la propiedad se encuentra en el propio objeto. Si es así, se devuelve esta propiedad.
  • Si la propiedad no se encuentra en el objeto en sí, 'ascenderá por el protochain'. Básicamente mira el objeto al que se refiere la propiedad proto. Allí comprueba si la propiedad está disponible en el objeto referido para proto
  • Si la propiedad no se encuentra en el objeto proto ascenderá por la cadena proto hasta el objeto Objeto.
  • Si no puede encontrar la propiedad en ninguna parte del objeto y su cadena de prototipo, devolverá undefined.

Por ejemplo:

function Person(name) {
  this.name = name;
}

let mySelf = new Person('Willem');

console.log(mySelf.__proto__ === Person.prototype);

console.log(mySelf.__proto__.__proto__ === Object.prototype);
 2
Author: Willem van der Veen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-18 10:24:20

Es solo que ya tienes un objeto con Objeto.nuevo pero aún no tiene un objeto cuando usa la sintaxis del constructor.

 1
Author: shiva kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-01 09:33:06

Otro esquema que muestra __proto__, prototipo y constructor relaciones: introduzca la descripción de la imagen aquí

 1
Author: IvanM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-02 06:21:42