2012-04-26 25 views
10
var someObj = function() { } 
var p = new someObj(); 

alert(someObj.prototype); // This works 
alert(p.prototype);   // UNDEFINED, but why? 

someObj.prototype.model= "Nissan"; 
alert(p.model);    // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype? 

¿Por qué es esto así? Como "p" es una instancia de "someObj", ¿por qué el prototipo está indefinido? Quiero decir, cuando agrego una propiedad al prototipo "algúnObj", es accesible a "p", entonces ¿por qué el prototipo no es accesible?Prototipo de Javascript a través de Object.create()

Respuesta

11

Lo importante aquí es que la propiedad prototype de los objetos de función no es el prototipo de un objeto. Es el objeto que se asignará como el prototipo de un objeto creado a través del new someObj. Antes de ES5, no puede acceder directamente al prototipo de un objeto; a partir de ES5, puede, a través del Object.getPrototypeOf.

Re

alert(p.prototype); // UNDEFINED, but why?

La razón es que el objeto p no tiene una propiedad llamada "prototipo". Tiene un prototipo subyacente, pero esa no es la forma de acceder a él.

Todos los objetos de función tienen una propiedad llamada prototype de modo que si se utilizan como funciones de constructor, podemos definir cuáles serán las propiedades del prototipo subyacente de los objetos creados por esos constructores. Esto puede ayudar:

function Foo() { 
} 
Foo.prototype.answer = 42; 

console.log(Foo.prototype.answer); // "42" 
var f = new Foo(); 
console.log(f.answer); // "42" 

Esa última línea funciona así:

  1. obtener el objeto f.
  2. Tiene f tiene su propia propiedad llamada "respuesta"?
  3. No, ¿el f tiene un prototipo?
  4. Sí, ¿el prototipo tiene su propia propiedad llamada "respuesta"?
  5. Sí, devuelva el valor de esa propiedad.

Usted mencionó Object.create en el título de su pregunta. Es importante entender que Object.create está bastante separado de las funciones del constructor. Se agregó al idioma para que, si prefirió no usar funciones de constructor, no tenga que hacerlo, pero aún así podría establecer el prototipo de un objeto   — directamente, cuando cree ese objeto.

+0

Excelente explicación –

+0

@TahaAhmad: ¡Me alegro de que haya ayudado! –

2

p.prototype no funciona porque en este caso p = someObj.prototype.

Básicamente, cuando utiliza el nuevo operador, lo que ocurre es que el constructor someObj se usa para inicializar un nuevo objeto. Lo que significa que devuelve un objeto que tiene las propiedades y métodos del prototipo del constructor.

Por lo tanto, p = someObj.prototype y p.prototype no está definido, ya que p no es un constructor.

Este artículo podría ayudar explica esto más

http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD

+0

Según la respuesta de Crowder, el prototipo está ahí y es accesible, mediante el uso de Object.getPrototypeOf (p). Si mi comprensión es correcta, las propiedades y los métodos se copian en nuevas instancias de objetos, pero eso no significa que p === someObj.prototype. Significa p.prototype === someObj.prototype –

1

p es un ejemplo de someObj. El prototipo pertenece al constructor. Puede recuperar prototipo constructor p 's utilizando p.constructor.prototype

6

Eso es porque prototype es una propiedad de la función constructora, no una propiedad de sí mismo. Sin embargo, el objeto prototype tiene una referencia al constructor, para que pueda acceder de prototype un objeto a través de su constructor propiedad:

function Foo() {} 

Foo.prototype.foo = "bar"; 

var c = new Foo; 

console.log(c.constructor === Foo); // true 
console.log(c.constructor.prototype); // { foo: 'bar' } 

Sin embargo, esto no funcionará si sobrescribe el prototype propiedad inicial de la función constructora:

function Foo() {} 

// I overwrite the prototype property, so I lose the initial reference 
// to the constructor. 
Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 

Es por eso que es mejor utilizar el nuevo método Object.getPrototypeOf introducido en ES5.

function Foo() {} 

Foo.prototype = { 
    foo: "bar" 
}; 

var c = new Foo; 

console.log(c.constructor === Foo); // false 
console.log(c.constructor === Object); // true 
console.log(c.constructor.prototype); // {} 
console.log(Object.getPrototypeOf(c)); // { foo: 'bar' } 

Otra solución habría sido para asegurarse de que restaura la referencia constructor en el prototipo:

function Foo() {} 

// Overwriting the initial prototype  
Foo.prototype = { 
    constructor: Foo, // restore the constructor reference 
    foo: "bar" 
}; 
+0

Encontré una publicación de blog extremadamente útil, que, combinada con esta respuesta, despeja una gran confusión acerca de la locura de todo el prototipo. http://blog.sklambert.com/javascript-prototype/ los diagramas ayudan mucho a entender esta respuesta. Espero que esto ayude a alguien. – Bruce

0

En Javascript, constructores, y de hecho todas las funciones de obtener una propiedad prototipo. Un objeto (es decir, un conjunto de pares clave-valor) no tiene una propiedad de prototipo. En el ejemplo anterior,

var someObj = function() { } // this is a function, so it has a prototype property 
var p = new someObj(); // this is an instance object, so it doesn't 

Por eso se define someObj.prototype, pero no es p.prototype.

Cuestiones relacionadas