¿Cómo funciona instanceof en JavaScript?

7 minutos de lectura

En el siguiente código, pruebe ambas comprobaciones de obj2 y obj3 al final con en vez de devolver verdadero incluso si las formas en que se construyeron son diferentes y los resultados de devolver nombre propiedad son diferentes.

var Obj1 = function() {
    this.name = "foo1";
};
Obj1.prototype.name = "foo1onProt";
var obj1 = new Obj1();

var Obj2 = function() {};
Obj2.prototype = new Obj1();
Obj2.prototype.constructor = Obj2;
var obj2 = new Obj2();

var Obj3 = function() {};
Obj3.prototype = Object.create(Obj1.prototype);
Obj3.prototype.constructor = Obj3;
var obj3 = new Obj3();

console.dir(obj1);
console.log("obj1.name: " + obj1.name);

console.dir(obj2);
console.log("obj2.name: " + obj2.name);

console.dir(obj3);
console.log("obj3.name: " + obj3.name);

console.log("obj2 instanceof Obj1: " + (obj2 instanceof Obj1));
console.log("obj3 instanceof Obj1: " + (obj3 instanceof Obj1));

Resultado de la ejecución en Chrome:

Obj1
  name: "foo1"
  __proto__: Object
    constructor: function () {
    name: "foo1onProt"
    __proto__: Object
obj1.name: foo1
Obj2
  __proto__: Obj1
    constructor: function () {}
    name: "foo1"
    __proto__: Object
      constructor: function () {
      name: "foo1onProt"
      __proto__: Object
obj2.name: foo1
Obj3
   __proto__: Object
   constructor: function () {}
   __proto__: Object
     constructor: function () {
     name: "foo1onProt"
     __proto__: Object
obj3.name: foo1onProt

obj2 instanceof Obj1: true
obj3 instanceof Obj1: true

¿Cuál es la mejor manera de reconocer que obj2 y obj3 ¿son diferentes? ¿Cómo en realidad en vez de ¿trabajar?

  • Crea dos objetos diferentes, ambos con Obj1 como base, y luego les pregunta si son instancias de Obj1. Bueno, sí, ambos lo son. Si quieres saber si son diferentes, simplemente usa el === operador.

    – AHM

    27 de junio de 2014 a las 13:49

  • @AHM Veo que su respuesta es de hace muchos años, sin embargo, nunca he visto un enfoque que utilice la igualdad estricta para comparar directamente los objetos de JavaScript. ¿Le importaría ampliar lo que quiso decir con su comentario anterior con respecto a ‘objA === objB’? desarrollador.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – AlphaG33k

    14 de febrero de 2021 a las 15:08

  • Para los objetos, el operador === devuelve verdadero solo si los dos objetos comparados son el mismo objeto. Si bien normalmente no compararía un objeto consigo mismo, esto puede ser útil si desea averiguar a qué objeto, de un conjunto conocido, tiene una referencia.

    – AHM

    16 de febrero de 2021 a las 10:38

avatar de usuario
TJ Crowder

¿Cuál es la mejor manera de reconocer que obj2 y obj3 son diferentes?

Eso dependerá en gran medida de lo que estés haciendo con ellos. Una forma sería usar instanceof Obj2 y instanceof Obj3. Dado que ambos objetos fueron creados con Obj1.prototype en su cadena de prototipos, tiene sentido que se identifiquen como una instancia de lo que llamaríamos el supertipo en la programación orientada a objetos basada en clases.

¿Cómo funciona realmente instanceof?

la versión corta

obj instanceof F mira para ver si el objeto al que hace referencia F.prototype está en cualquier parte objcadena de prototipos. no usa constructor en absoluto.

Más detalles

Esto está cubierto en la especificación por §11.8.5 – La instancia del Operadorque dice (indirectamente, vía §8.6.2) que llama el [[HasInstance]] método interno del objeto de la función, pasando el objeto que estamos probando. Function‘s [[HasInstance]] (en §15.3.5.3) dice que obtiene la referencia del objeto de la función prototype propiedad y luego regresa true si ese objeto está en algún lugar de la cadena de prototipos del objeto de destino, false si no es así

no usa constructor (de hecho, nada en JavaScript lo hace), y si lo piensa, no puede, porque un objeto constructor La propiedad solo puede apuntar a una función, pero un objeto puede ser instanceof múltiples funciones, por ejemplo, en el caso de la herencia pseudoclásica:

function F1() {}

function F2() {
  F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;

var obj = new F2();
console.log(obj instanceof F1); // true
console.log(obj instanceof F2); // true

Ambos son verdaderos porque los dos objetos a los que hace referencia F1.prototype y F2.prototype ambos están en objcadena de prototipos.

instanceof ser cierto no significa necesariamente que obj fue creado por una llamada a F, ya sea directa o indirectamente; simplemente indica que hay un vínculo vago entre ellos (F.prototype se refiere a un objeto que también está en objcadena de prototipos). Eso normalmente medio F participó en la creación del objeto, pero no hay garantía.

Por ejemplo:

function F() {}
var obj = Object.create(F.prototype);
console.log(obj instanceof F); // true

Tenga en cuenta que F no fue llamado para crear el objeto, en absoluto.


O quizás más clara y/o dramáticamente:

function F() {}
var p = {};
var obj = Object.create(p);
console.log(obj instanceof F); // false
F.prototype = p;
console.log(obj instanceof F); // true

También existe esta versión inusual, pero totalmente posible:

function F1() {}
function F2() {}
F1.prototype = F2.prototype = {};
var obj = new F1();
console.log(obj instanceof F2); // true

O este:

function F1() {}
function F2() {}
var obj = new F2();
console.log(obj instanceof F1); // false
F1.prototype = F2.prototype;
console.log(obj instanceof F1); // true

  • @VLAZ: gracias, no sabía que ninguna de mis respuestas aún usaba eso. tendré que ir de cacería…

    –TJ Crowder

    24 de junio de 2020 a las 8:23

  • oh, cierto… También quise escribir un comentario para notificarte. Me olvidé de eso durante la edición. 🙂 Además, traté de encontrar el repositorio, pero parece que se ha ido, supongo que porque ya no es necesario.

    – VLAZ

    24 de junio de 2020 a las 8:27

  • @VLAZ: no es necesario que deje un comentario, SO le notifica cuando se edita su respuesta. 🙂 No recuerdo haber eliminado ese repositorio, pero parece más probable que lo haya hecho que que github lo haya perdido. 😀 Ugh, el explorador de datos dice que tengo 349 de estos para arreglar… ;-( A dos minutos por, eso es casi 12 horas de trabajo. Haré 5-10 por día durante un mes o dos…

    –TJ Crowder

    24 de junio de 2020 a las 8:31


  • Tal vez tu puedas automatizarlo 🙂 También puedo echar una mano de vez en cuando. Recientemente he comenzado a actualizar algunas publicaciones antiguas, principalmente haciendo que los fragmentos sean ejecutables. Todavía estoy explorando formas de encontrar qué publicaciones actualizar, principalmente estoy navegando y revisando preguntas y respuestas completas que me llaman la atención. Por lo tanto, no está guiado y es esporádico por ahora: sus publicaciones brindan un objetivo más directo por el que puedo trabajar.

    – VLAZ

    24 de junio de 2020 a las 8:46

  • @VLAZ – ¡Eso es muy amable! Puedo hacerlo a cuentagotas, pero si quieres colaborar, aquí está la lista, simplemente cambie cualquier cosa que haga para tachar el texto (no los elimine). Si ve alguno con mi arte ASCII de estilo antiguo usando – en lugar de -, ¿podría agregar una nota? Iré a arreglarlos. 🙂 Pero otra vez, solamente si realmente quieres, me pondré en contacto con ellos de otra manera. (Ya he hecho algunos que no están en esa lista, así que ya no es 349…)

    –TJ Crowder

    24 de junio de 2020 a las 9:07


avatar de usuario
svidgen

Más simplemente: obj instanceof constructor rendimientos true cuando obj posee constructorEl prototipo en su cadena de constructor/prototipo. En otras palabras, le está preguntando a su motor si obj puede ser tratado como un caso de constructor / ya sea obj se comporta como un constructor objeto.

Hay un pequeño puñado de sintaxis que le permiten poner constructorprototipo en objcadena de prototipos. Cualquiera y todos ellos causarán obj instanceof constructor ser – estar true. En tus ejemplos, ambos obj2 y obj3 tener Obj1 en su cadena de prototipos.

Entonces, cuando le pregunta a su motor de javascript si o obj2 o obj3 comportarse como una instancia de Obj1JavaScript asume true — el único caso en el que no lo harían es si ha anulado Obj1el comportamiento de la línea.

  • @FrédéricHamidi Buena distinción.

    – svidgen

    27 de junio de 2014 a las 13:51

  • Esta es una respuesta incorrecta. La respuesta de TJ Crowder es correcta.

    – WebBrother

    26 de abril de 2018 a las 13:16

function F1() {}

function F2() {
  F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;

var obj = new F2();
console.log(obj instanceof F1); // true
console.log(obj instanceof F2); // true

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad