2010-03-17 21 views
35

En algunos de mi propio código antiguo, utilizo el siguiente:¿Cuál es la diferencia entre isPrototypeOf y instanceof en Javascript?

Object.prototype.instanceOf = function(iface) 
{ 
return iface.prototype.isPrototypeOf(this); 
}; 

Entonces hacer (por ejemplo)

[].instanceOf(Array) 

Esto funciona, pero parece que el siguiente sería hacer lo mismo:

[] instanceof Array 

Ahora, seguramente este es solo un ejemplo muy simple. Mi pregunta por lo tanto es:

¿Es a instanceof bSIEMPRE lo mismo que b.prototype.isPrototypeOf(a)?

+0

Si bien siempre puedes usar 'instanceof' (con constructores en el RHS), no todos los objetos pueden heredar de' Object.prototype'. 'Object.create (null) instanceof Something' y' ({}). InstanceOf ({prototype: Something.prototype}) 'funcionará (y generará' false') donde fallaría el reverso. – Bergi

Respuesta

25

Sí, hacen lo mismo, ambos recorren la cadena del prototipo buscando un objeto específico en ella.

La diferencia entre ambos es lo que son, y cómo los usa, p. Ej. la isPrototypeOf es una función disponibles en el objeto Object.prototype, que le permite probar si un objeto específico se encuentra en la cadena de prototipo del otro, ya que se define este método en Object.prototype, es estar disponible para todos los objetos.

instanceof es un operador y espera dos operandos, un objeto y un Constructor function, probará si la función pasado existe prototype propiedad en la cadena del objeto (a través de la operación interna [[HasInstance]](V), disponible únicamente en objetos de función)

Por ejemplo:

function A() { 
    this.a = 1; 
} 
function B() { 
    this.b = 2; 
} 
B.prototype = new A(); 
B.prototype.constructor = B; 

function C() { 
    this.c = 3; 
} 
C.prototype = new B(); 
C.prototype.constructor = C; 

var c = new C(); 

// instanceof expects a constructor function 

c instanceof A; // true 
c instanceof B; // true 
c instanceof C; // true 

// isPrototypeOf, can be used on any object 
A.prototype.isPrototypeOf(c); // true 
B.prototype.isPrototypeOf(c); // true 
C.prototype.isPrototypeOf(c); // true 
+1

Entonces, ¿la única diferencia es que puedo usar isPrototypeOf, si solo tengo el prototipo, mientras que necesito el constructor para instanceof? (¿Haciendo mi función realmente idéntica a instanceof?) –

+1

Su respuesta de texto es útil, su ejemplo de código es menor. (Solo muestra aspectos iguales pero no diferencias.) Sin embargo, me plantea otra pregunta: ¿para quién es ".constructor"? He visto ese código en algunos lugares, pero nunca lo escribí yo mismo y no parece haberlo necesitado.(Por lo general, tenía algo así como 'C.prototype.clazz = C;' tough.) ¿Por qué las personas establecen el constructor? –

+1

@Steffen Heil: el código escrito por CMS es lo suficientemente claro, creo, utiliza la forma más simple y conocida (aunque no es la más efectiva) de heredar en JavaScript entre constructores. Intente eliminar la línea 'B.prototype.constructor = B' e inspeccione el constructor de una instancia de B:' alert ((new B) .constructor) 'y verá el constructor de la función A. Al hacer eso, se asegura de encontrar, como constructor de todas las instancias de B, solo B. –

0

precedencia del operador y de truthiness difieren ya que una es una expresión y la otra es una llamada al método. Una cosa a destacar es que tanto atraviesan la cadena de prototipo, por lo que no se puede asumir que existe una correlación uno a uno entre un prototipo a juego y el objeto en cuestión:

var i = 0; 
 

 
function foo() 
 
{ 
 
console.log("foo"); 
 
console.log(i++ + ": " + Object.prototype.isPrototypeOf(Object)) //true 
 
console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function)) //true 
 

 
console.log(i++ + ": " + Function.prototype.isPrototypeOf(Function)) //true 
 
console.log(i++ + ": " + Function.prototype.isPrototypeOf(Object)) //true 
 

 
console.log(i++ + ": " + RegExp.prototype.isPrototypeOf(RegExp(/foo/))) //true 
 
console.log(i++ + ": " + Object.prototype.isPrototypeOf(RegExp(/foo/))) //true 
 
console.log(i++ + ": " + Function.prototype.isPrototypeOf(RegExp(/foo/))) //false 
 
console.log(i++ + ": " + Object.prototype.isPrototypeOf(Math)) //true 
 
console.log(i++ + ": " + Math.isPrototypeOf(Math)) //false 
 
} 
 

 
function bar() 
 
{ 
 
console.log("bar"); 
 
console.log(i++ + ": " + (Object instanceof Object)) //true 
 

 
console.log(i++ + ": " + (Function instanceof Function)) //true 
 
console.log(i++ + ": " + (Function instanceof Object)) //true 
 

 
console.log(i++ + ": " + (RegExp(/foo/) instanceof RegExp)) //true 
 
console.log(i++ + ": " + (RegExp(/foo/) instanceof Object) ) //true 
 
console.log(i++ + ": " + (RegExp(/foo/) instanceof Function)) //false 
 
console.log(i++ + ": " + (Math instanceof Object)) //true 
 
console.log(i++ + ": " + (Math instanceof Math)) //error 
 
} 
 
try 
 
    { 
 
    foo() 
 
    } 
 
catch(e) 
 
    { 
 
    console.log(JSON.stringify(e)); 
 
    } 
 
finally 
 
    { 
 
    try 
 
    { 
 
    bar(); 
 
    } 
 
    catch(e) 
 
    { 
 
    console.log(JSON.stringify(e)); 
 
    } 
 
    }

Referencias

Cuestiones relacionadas