Traducción en curso

JavaScript está diseñado sobre un paradigma simple basado en objetos. Un objeto es una colección de propiedades, y una propiedad es una asociación entre un nombre (o clave) y un valor. Un valor de una propiedad puede ser una función, en cuyo caso la propiedad es conocida. Además de los objetos que están predefinidos en el navegador, puedes definir tus propios objetos.
Este capítulo describe cómo usar objetos, propiedades, funciones, y métodos, y cómo crear tus propios objectos.

Visión general sobre los Objetos

Los objetos en JavaScript, como en tantos otros lenguajes de programación, pueden ser comparados con objetos de la vida real. El concepto de Objetos en JavaScript puede entenderse con objetos tangibles de la vida real.

En JavaScript, un objeto es un entidad independiente con propiedades y tipos. Compáralo con una taza, por ejemplo. Una taza es un objeto con propiedades. Una taza tiene un color, un diseño, tiene peso y un material con la que fue hecha, etc. De la misma manera, los objetos de JavaScript pueden tener propiedades, las cuales definen sus características.

Objetos y propiedades

Un objeto de JavaScript tiene propiedades asociadasa él. Una propiedad de un objeto puede ser explicada como una variable adjunta al objeto. Las propiedades de un objeto son basicamente lo mismo que las variables comunes de JavaScript, excepto por el nexo con el objeto. Las propiedades de un objeto definen las características de un objeto; se puede acceder a ellas con una simple notación de puntos:

nombreObjeto.nombrePropiedad

Como todas las variables de JavaScript, tanto el nombre del objeto (que puede ser una variable normal) y el nombre de propiedad son sensible a mayúsculas y minúsculas. Puedes definir propiedades asignándoles un valor. Por ejemplo, vamos a crear un objeto llamado miAuto y le vamos a asignar propiedades denominadas marca, modelo, y año de la siguiente manera:

var miAuto = new Object();
miAuto.marca = "Ford";
miAuto.modelo = "Mustang";
miAuto.año = 1969;

Las propiedades no asignadas de un objeto son undefined (y no null).

miAuto.color; // undefined

Las propiedades de los objetos en JavaScript también se puede accedidas o establecidas mediante la notación de corchetes [ ](Para más detalle ver property accesors). Los objetos son llamados a veces arreglos asociativos, ya que cada propiedad está asociada con un valor de cadena que puede ser utilizada para acceder a ella. Así, por ejemplo, puedes acceder a las propiedades del objeto miAuto de la siguiente manera:

miAuto["marca"] = "Ford";
miAuto["modelo"] = "Mustang";
miAuto["año"] = 1969; 

El nombre de la propiedad de un objeto puede ser cualquier cadena válida de JavaScript, o cualquier cosa que se pueda convertir en una cadena, incluyendo una cadena vacía. Sin embargo, cualquier nombre de propiedad que no sea un identificador válido de JavaScript (por ejemplo, el nombre de alguna propiedad que tenga un espacio o un guión, o comienza con un número) sólo puede ser accedido utilizando la notación de corchetes. Esta notación es muy útil también cuando los nombres de propiedades son determinados dinámicamente (cuando el nombre de la propiedad no se determina hasta su tiempo de ejecución). Ejemplos de ésto se muestran a continuación:

var miObjeto = new Object(),
    cadena = "miCadena",
    aleatorio = Math.random(),
    objeto = new Object();

miObjeto.type                 = "Sintaxis con punto";
miObjeto["Fecha de creación"] = "Cadena con espacios y acento";
miObjeto[cadena]              = "String value";
miObjeto[aleatorio]           = "Número Aleatorio";
miObjeto[objeto]              = "Objeto";
miObjeto[""]                  = "Incluso una cadena vacía";

console.log(miObjeto);

Por favor, advierte que todas las claves con notación en corchetes son convertidas a string a menos que éstas sean Symbols, ya que los nombres de las propiedades (claves) en Javascript pueden ser sólo strings o Symbols (en algún momento, los nombres privados también serán agregados a medida que la propuesta de los campos de la clase progrese, pero no las usarás con el formato []). Por ejemplo, en el código anterior, cuando la clave objeto es añadida a miObjeto, Javascript llamará al método obj.toString(), y usará el resultado de ésta llamada (string) como la nueva clave.

También puedes acceder a las propiedades mediante el uso de un valor de cadena que se almacena en una variable:

var nombrePropiedad = "marca";
miAuto[nombrePropiedad] = "Ford";

nombrePropiedad = "modelo";
miAuto[nombrePropiedad] = "Mustang";
Puedes utilizar la notación de corchetes con for ... in para iterar sobre todas las propiedades enumerables de un objeto. Para ilustrar cómo funciona esto, la siguiente función muestra las propiedades del objeto cuando pasas como argumentos de la función el objeto y el nombre del objeto:
 
function mostrarPropiedades(objeto, nombreObjeto) {
  var resultado = ``;
  for (var i in objeto) {
    //objeto.hasOwnProperty se usa para filtrar las propiedades del objeto
    if (objeto.hasOwnProperty(i)) {
        resultado += `${nombreObjeto}.${i} = ${objeto[i]}\n`;
    }
  }
  return resultado;
}

Por lo tanto, la llamada a la función mostrarPropiedades(miAuto, "miAuto") retornaría lo siguiente:

console.log(mostrarPropiedades(miAuto, "miAuto") );
miAuto.marca = Ford
miAuto.modelo = Mustang
miAuto.annio = 1969

Listar las propiedades de un objeto

A partir de ECMAScript 5, hay tres formas nativas para listar/atravezar propiedades de objeto:

  • bucles for...in
    Este método atraviesa todas las propiedades enumerables de un objeto y su cadena de prototipo
  • Object.keys(o)
    Este método devuelve una matriz con todos los nombres de propiedades ("keys") enumerables y propias (no de la cadena de prototipos) de un objeto o.
  • Object.getOwnPropertyNames(o)
    Este método devuelve una matriz que contiene todos los nombres (enumerables o no) de las propiedades de un objeto o.

Antes de ECMAScript 5, no existía una manera nativa para listar todas las propiedades de un objeto. Sin embargo, esto se puede lograr con la siguiente función:

function listaTodasLasPropiedades(o){
   var objetoAInspeccionar;
   var resultado = [];

   for(objetoAInspeccionar = o; objetoAInspeccionar !== null; objetoAInspeccionar = Object.getPrototypeOf(objetoAInspeccionar)){
      resultado = resultado.concat(Object.getOwnPropertyNames(objetoAInspeccionar)) + "\n";
   }   

   return resultado; 

}

Esto puede ser útil para revelar las propiedades "ocultas" (propiedades de la cadena de prototipo a las que no se puede acceder a través del objeto, porque otra propiedad tiene el mismo nombre en la cadena de prototipo). Listar las propiedades accesibles sólo es posible eliminando los duplicados en el matriz.

Creando nuevos objetos

JavaScript tiene un número de objetos predefinidos. Además, puedes crear tus propios objetos. En JavaScript 1.2 y versiones posteriores, puedes crear un objeto usando un inicializador de objeto. Como alternativa, puedes crear primero una función constructora y luego crear una instancia de un objeto invocando esa función con el operador new.
 

El uso de inicializadores de objeto

Además de la creación de objetos utilizando una función constructora, puedes crear objetos utilizando un inicializador de objeto. El uso de los inicializadores de objeto se refiere a veces a como crear objetos con la notación literal. "Inicializador de objeto" es consistente con la terminología utilizada por C++.
 

La sintaxis para un objeto usando un inicializador de objeto es:

var objeto = { propiedad_1  : valor_1,   // propiedad_# puede ser un identificador...
               2:             valor_2,   // o un numero...
               // ...,
               "propiedad n": valor_n }; // o una cadena

donde objeto es el nombre del nuevo objeto, cada propiedad_i es un identificador (ya sea un nombre, un número o una cadena literal), y cada valor_i es una expresión cuyo valor es asignado a la propiedad_i. El objeto y la asignación es opcional; si no necesitas hacer referencia a este objeto desde otro lugar, no necesitas asignarlo a una variable. (Ten en cuenta que tal vez necesites envolver el objeto literal entre paréntesis si el objeto aparece donde se espera una declaración, a fin de no confundir el literal con una declaración de bloque.) 

Los inicializadores de objetos son expresiones, y cada inicializador de objeto da como resultado un nuevo objeto donde la instrucción de creación sea ejecutada. Los inicializadores de objetos idénticos crean objetos distintos que no se compararán entre sí como iguales. Los objetos se crean como si se hiciera una llamada new Objet(); esto es, los objetos hechos de expresiones literales de objetos son instancias de Object.

La siguiente declaración crea un objeto y lo asigna a la variable x si y sólo si la expresión cond es true.

if (cond) var x = {saludo: "Hola!"};

El siguiente ejemplo crea miHonda con tres propiedades. Observa que la propiedad motor es también un objeto con sus propias propiedades.

var miHonda = {color: "rojo", ruedas: 4, motor: {cilindros: 4, tamanio: 2.2}};
También puedes utilizar inicializadores de objetos para crear matrices. Consulta array literals.
 

En JavaScript 1.1 y versiones anteriores, no se puede utilizar inicializadores de objeto. Puedes crear objetos usando sólo sus funciones constructoras o utilizando una función suministrada por algún otro objeto para ese propósito. Consulta Using a constructor function.

Usando una función constructora

Como alternativa, puedes crear un objeto con estos dos pasos:

  1. Definir el tipo de objeto escribiendo una función constructora. Existe una fuerte convención, con buena razón, para utilizar en mayúscula la letra inicial.
  2. Crear una instancia del objeto con el operador new.

Para definir un tipo de objeto, crea una función para el objeto que especifique su nombre, propiedades y métodos. Por ejemplo, supongamos que deseas crear un tipo de objeto para los coches. Quieres llamar Auto a este tipo de objeto, y deseas que tenga las siguientes propiedades: marca, modelo y el año. Para ello, podrías escribir la siguiente función:

function Auto(marca, modelo, annio) {
  this.marca = marca;
  this.modelo = modelo;
  this.annio = annio;
}

Observa el uso de this para asignar valores a las propiedades del objeto en función de los valores pasados ​​a la función.

Ahora puedes crear un objeto llamado miAuto de la siguiente manera:

var miAuto = new Auto("Eagle", "Talon TSi", 1993);

Esta declaración crea miAuto y le asigna los valores especificados a sus propiedades. Entonces el valor de miAuto.marca es la cadena "Eagle", para miAuto.annio es el número entero 1993, y así sucesivamente.

Puedes crear cualquier número de objetos Auto con las llamadas a new. Por ejemplo,

var kenscar = new Auto("Nissan", "300ZX", 1992);
var vpgscar = new Auto("Mazda", "Miata", 1990); 

Un objeto puede tener una propiedad que es en sí mismo otro objeto. Por ejemplo, supongamos que defines un objeto llamado persona de la siguiente manera:

function Persona(nombre, edad, sexo) {
  this.nombre = nombre;
  this.edad = edad;
  this.sexo = sexo;
}

y luego instancias dos nuevos objetos Persona de la siguiente manera:

var fer = new Persona("Fernando Duclouk", 38, "M");
var alvaro = new Persona("Alvaro Caram", 36, "M");

Entonces, puedes volver a escribir la definición de Auto para incluir una propiedad propietario que tomará el objeto persona, de la siguiente manera:

function Auto(marca, modelo, annio, propietario) {
  this.marca = marca;
  this.modelo = modelo;
  this.annio = annio;
  this.propietario = propietario;
}

Para crear instancias de los nuevos objetos, utiliza lo siguiente:

var auto1 = new Auto("Eagle", "Talon TSi", 1993, fer);
var auto2 = new Auto("Nissan", "300ZX", 1992, alvaro);

Nota que en lugar de pasar un valor de cadena o entero cuando se crean los nuevos objetos, las declaraciones anteriores pasan al objetos fer y alvaro como argumetnos para propietario. Si luego quieres averigüar el nombre del propietario del auto2, puedes acceder a la propiedad de la siguiente manera:

auto2.propietario.nombre

Ten en cuenta que siempre se puede añadir una propiedad a un objeto previamente definido. Por ejemplo, la declaración

auto1.color = "negro";

agrega la propiedad color a auto1, y le asigna el valor "negro". Sin embargo, esto no afecta a ningún otro objeto. Para agregar la nueva propiedad a todos los objetos del mismo tipo, tienes que la propiedad a la definición del tipo de objeto Auto.

Usando el método Object.create

Los objetos también se pueden crear mediante el método Object.create. Este método puede ser muy útil, ya que te permite elegir el prototipo del objeto que deseas crear, sin tener que definir una función constructora.

// Propiedades y método de encapsulación para Animal
var Animal = {
  tipo: 'Invertebrados', // valor por defecto de la propiedad
  mostrarTipo: function() {  // Método que mostrará el tipo de Animal
    console.log(this.tipo);
  }
};

// Crear una nuevo objeto de tipo Animal llamado animal1 
var animal1 = Object.create(Animal);
animal1.mostrarTipo(); // Salida: Invertebrados

// Crear una nuevo objeto de tipo Animal llamado y asignar 'Pescados' a la propiedad tipo
var fish = Object.create(Animal);
fish.tipo = 'Pescados';
fish.mostrarTipo(); // Salida: Pescados

Para obtener información más detallada sobre el método y la forma de usarlo, consulte Object.create().

Herencia

Todos los objetos en JavaScript heredan al menos otro objeto. El objeto del cuál está siendo heredado se conoce como el prototipo, y las propiedades heredadas se pueden encontrar en el objeto prototype del constructor. Para más información consultar Herencia y cadena del prototipo.

Propiedades del objeto indexado

En JavaScript 1.0, puede hacer referencia a una propiedad de un objeto, ya sea por su nombre de la propiedad o por su índice ordinal. En JavaScript 1.1 y posteriores, sin embargo, si inicialmente definimos una propiedad por su nombre, debe referirse siempre a ella por su nombre, y si inicialmente definimos una propiedad por un índice, siempre debe referirse a ella por su índice.

 

Esta restricción se aplica cuando creas un objeto y sus propiedades con una función constructora (como hicimos antes con el tipo de objeto Auto) y cuando defines propiedades individuales de forma explícita (por ejemplo, miAuto.color = "rojo").  Si inicialmente defines una propiedad de objeto con un índice, como miAuto[5] = "25 mpg", puedes hacer referencia posteriormente a la propiedad sólo como miAuto[5].

La excepción a esta regla son los objetos HTML, como por ejemplo los objetos contenidos en formularios. Siempre se puede hacer referencia a objetos en los formularios, ya sea por su número ordinal (basado en el lugar donde aparecen en el documento) o su nombre (si está definida). Por ejemplo, si la segunda etiqueta <FORM> en un documento tiene un atributo NAME con valor "myForm", puedes hacer referencia al formulario como document.forms [1] o document.forms ["myForm"] o document.myForm.
 

Definición de las propiedades de un tipo de objeto

Puedes agregar una propiedad a un tipo de objeto definido previamente mediante el uso de la propiedad prototype. Esto define una propiedad que es compartida por todos los objetos del tipo especificado, en lugar de por una sola instancia del objeto. El siguiente código agrega una propiedad color a todos los objetos del tipo Auto, y luego asigna un valor a la propiedad color del objeto auto1.

Auto.prototype.color = null;
auto1.color = "negro";

Para más información, ver la propiedad prototype del objeto Function en la Referencia de JavaScript.

Definiendo los métodos

Un método es una función asociada a un objeto, o, simplemente, un método es una propiedad de un objeto que es una función. Los métodos se definen normalmente como una función, con excepción de que tienen que ser asignados como la propiedad de un objeto. Un ejemplo puede ser:

nombreDelObjeto.nombreDelMetodo = nombreDeLaFuncion;

  var miObjeto = {
       miMetodo: function(parametros) {
         // ...hacer algo
      }
      //O ESTO TAMBIÉN FUNCIONA
      miOtroMetodo(parametros){
         // ... hacer otra cosa
     }
}; 

donde nombreDelObjeto es un objeto existente, nombreDelMetodo es el nombre que se le va a asignar al método, y nombreDeLaFuncion es el nombre de la función.

Entonces puedes llamar al método en el contexto del objeto de la siguiente manera:

object.nombreDelMetodo(parametros);
Puedes definir métodos para un tipo de objeto incluyendo una definición del método en la función constructora del objeto. Podrías definir una función que formatée y muestre las propiedades de los objetos del tipo Auto previamente definidos; por ejemplo:
 
function mostrarAutos() {
  var resultado = `Un bonito ${this.marca} ${this.modelo} ${this.annio}`;
  imprimir_con_estilo(resultado);
}

donde imprimir_con_estilo es una función para mostrar una línea horizontal y una cadena. Observa el uso de this para referirse al objeto al que pertenece el método.

Puedes hacer de esta función un método de Auto agragando la declaración

this.mostrarAutos = mostrarAutos;

a la definición del objeto. Por lo tanto, la definición completa de Auto ahora se vería así:

function Auto(marca, modelo, annio, propietario) {
  this.marca = marca;
  this.modelo = modelo;
  this.annio = annio;
  this.propietario = propietario;
  this.mostrarAutos = mostrarAutos;
}

Entonces puedes llamar al método mostrarAutos para cada uno de los objetos de la siguiente manera:

auto1.mostrarAuto();
auto2.mostrarAuto();

Esto produce el resultado que se muestra en la siguiente figura.

Un bonito Eagle Talon TSi 1993
Un Bonito Nissan 300ZX 1992

Figura 7.1: Muestra el resultado del método.

Usando this para las referencias a objetos

JavaScript tiene una palabra clave especial, this, que puedes usar dentro de un método para referirte al objeto actual. Por ejemplo, supongamos que tenemos una función llamada validar que valida el valor de la propiedad de un objeto, teniendo en cuenta al objeto y los valores altos y bajos:

function validar(objeto, valorbajo, valoralto) {
  if ((objeto.value < valorbajo) || (objeto.value > valoralto))
    alert("Valores no válidos!");
}

Entonces, puedes llamar a validar en el controlador de eventos onchange de cada elemento del formulario, usando this para  pasarle el elemento, como en el siguiente ejemplo:

<input type="text" name="edad" size="3"
  onChange="validar(this, 18, 99)"> 

En general, this se refiere al objeto de llamada en un método. 

Cuando lo combinamos con la propiedad form, this puede referirse al objeto actual del formulario principal. En el siguiente ejemplo, el formulario miForm contiene un objeto de texto y un botón. Cuando el usuario hace clic en el botón, el nombre del formulario se asigna al valor del texto en el formulario. El manejador de eventos del botón onclick utiliza this.form para referirse al formulario principal, myForm.
 
<form name="miForm">
<p><label>Nombre del formulario:<input type="text" name="text1" value="Beluga"></label>
<p><input name="button1" type="button" value="Mostrar Nombre del Formulario"
     onclick="this.form.text1.value = this.form.name">
</p>
</form>

Definiendo getters y setters

Un getter es un método que obtiene el valor de una propiedad específica.  Un setter es un método que establece el valor de una propiedad específica. Puede definir getters y setters en cualquier objeto central predefinido u objeto definido por el usuario que admita la adición de nuevas propiedades. La sintaxis para definir getter y setters utiliza la sintaxis literal de un objeto.

JavaScript 1.8.1 Nota:
Partir de JavaScript 1.8.1, los setters ya no son llamados a la hora de establecer las propiedades en los objetos y matrices inicializadores.

La siguiente sesión de JS shell ilustra como getters y setters podrían trabajar para un objeto o definido por el usuario. El JS shell es una aplicación que permite a los desarrolladores probar código JavaScript en modo por lotes o interactiva. En Firefox puede obtener un JS shell pulsando Ctrl + Shift + K.

js> var o = {a: 7, get b() {return this.a + 1;}, set c(x) {this.a = x / 2}};
[object Object]
js> o.a;
7
js> o.b;
8
js> o.c = 50;
js> o.a;
25

Las propiedades del objeto o son:

  • o.a — un número
  • o.b — un getter que devuelve o.a más 1
  • o.c — un setter que establece el valor de o.a a la mitad del valor que este seteado o.c
Ten en cuenta que los nombres de las funciones getters y setters definidos en un literal de objeto utilizando "[gs] et property()" (a diferencia de __define[GS]etter__ ) no son los nombres de los propios getters, aunque la sintaxis de [gs]et propertyName(){} puede inducir a pensar lo contrario. Para nombrar una función en un getter o setter utilizando la sintaxis "[gs]et property()", define una función nombrada explícitamente mediante programación usando Object.defineProperty ( o El retorno heredado de Object.prototype.__defineGetter__ ).
 

Esta sesión de shell de JavaScript ilustra como getters y setters pueden extender el prototipo de Date para agregar una propiedad year a todas las instancias de la clase predefinida Date. Utiliza los métodos existentes getFullYear y setFullYear de la clase Date para dar soporte a las propiedades getter y setter de year.

Estas declaraciones definen un getter y setter para la propiedad year:

js> var d = Date.prototype;
js> Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

Estas declaraciones utilizan el getter y setter de un objeto Date:

js> var now = new Date;
js> print(now.year);
2000
js> now.year = 2001;
987617605170
js> print(now);
Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001

Resumen

En principio, getters y setters pueden ser

  • definidos utilizando los inicializadores de objeto, o
  • agregados después a cualquier objeto en cualquier momento utilizando un método getter o setter añadido.
Cuando se define getters y setters utilizando los inicializadores de objeto todo lo que tienes que hacer es anteponer un método getter con get y un método setter con setPor supuesto, el método getter no debe esperar un parámetro, mientras que el método setter espera exactamente un parámetro (el nuevo valor a definir). Por ejemplo:
 
var o = {
  a: 7,
  get b() { return this.a + 1; },
  set c(x) { this.a = x / 2; }
};
Los getters y setters también pueden añadirse a un objeto en cualquier momento después de su creación utilizando el método Object.defineProperties. El primer parámetro de este método es el objeto sobre el que se quiere definir el getter o setter.  El segundo parámetro es un objeto cuyo nombre de propiedad son los nombres getter o setter, y cuyos valores de propiedad son objetos para la definición de las funciones getter o setter. Aquí hay un ejemplo que define el mismo getter y setter utilizado en el ejemplo anterior:
 
var o = { a:0 }

Object.defineProperties(o, {
    "b": { get: function () { return this.a + 1; } },
    "c": { set: function (x) { this.a = x / 2; } }
});

o.c = 10          // Ejecuta el setter, que asigna 10/2 (5) a la propiedad 'a'
console.log(o.b)  // Ejecuta el getter, que produce a + 1 o 6 

 

¿Cuál de las dos formas elegir? Sepende de tu estilo de programación y de la tarea que te ocupa. Si ya utilizas el inicializador de objeto al definir un prototipo probablemente escojas la primer forma la mayoría de las veces. Esta forma es más compacta y natural. Sin embargo, si necesitas agregar getters y setters más tarde  porque no escribiste el objeto prototipo o particular  — entonces la segunda forma es la única forma posible. La segunda forma, probablemente representa mejor la naturaleza dinámica de JavaScript  pero puede hacer que el código sea difícil de leer y entender.

Antes de Firefox 3.0, getter y setter no eran compatibles con los elementos del DOM. Las versiones anteriores de Firefox fallan silenciosamente. Si se necesitan excepciones para aquellos que, al cambiar el prototipo de HTMLElement (HTMLElement.prototype.__define [SG] etter__ ) y lanzar una excepción es una solución.

Con Firefox 3.0 , definiendo getter o setter en una propiedad ya definida se producirá una excepción. La propiedad debe ser eliminada previamente, lo cual no es el caso para las versiones anteriores de Firefox.

 

Sintaxis obsoletas

En el pasado, JavaScript daba apoyo a otras sintaxis diferentes para la definición de getters y setters. Ninguna de estas sintaxis fueron apoyadas por otros motores, y el apoyo se ha eliminado en las últimas versiones de JavaScript. Ver esta disección de la sintaxis removida para obtener más detalles sobre lo que fue eliminado y la forma de adaptarse a esta supresión.

También vea

Eliminando propiedades

Puedes eliminar una propiedad no heredada mediante el operador delete. El siguiente código muestra cómo eliminar una propiedad.

//Crea un nuevo objeto, miobjeto, con dos propiedades, a y b.
var miobjeto = new Objecto;
miobjeto.a = 5;
miobjeto.b = 12;

//Elimina la propiedad, dejando miobjeto con sólo la propiedad b.
delete myobj.a;
console.log ("a" in myobj) // yields "false"

También puedes utilizar delete para eliminar una variable global si la palabra clave var no fue utiliza para declarar la variable:

g = 17;
delete g;

Vea delete para más información.

Comparando Objetos

Como sabemos los objetos son de tipo referencia en JavaScript. Dos objetos con las mismas propiedades  métodos  nunca son iguales. Sólo comparando la misma referencia al objeto consigo mismo dará como resultado true.
 
// variable de referencia del objeto fruta
var fruta = {nombre: "manzana"};

// variable de referencia del objeto fructificar
var fructificar = {nombre: "manzana"};

fruta == fructificar // retorna false
fruta === fructificar // retorna false
// variable de referencia del objeto fruta
var fruta = {nombre: "manzana"};

// variable de referencia del objeto fructificar
var fructificar = fruta; // asignamos la referencia del objeto fruta a la variable de referencia del objeto fructificar

// aquí fruta y fructificar apuntan al mismo objeto llamado fruta
fruta == fructificar // retorna true

// aquí fruta y fructificar apuntan al mismo objeto llamado fruta
fruta === fructificar // retorna true

 

Nota: El operador "===" se utiliza para comprobar el valor así como el tipo, ejemplo: 
1 === "1"  // retorna false
1 == "1"   // retorna true

Véase también