¿Cuál es la mejor manera de crear un objeto en JavaScript? ¿Es necesario 'var' antes de una propiedad de objeto?

177

Hasta ahora vi tres formas de crear un objeto en JavaScript. ¿Cuál es la mejor manera de crear un objeto y por qué?

También vi que en todos estos ejemplos la palabra clave varno se usa antes de una propiedad, ¿por qué? ¿No es necesario declarar varantes del nombre de una propiedad ya que mencionó que las propiedades son variables?

En la segunda y tercera forma, el nombre del objeto está en mayúscula, mientras que en la primera forma el nombre del objeto está en minúscula. ¿Qué caso debemos usar para un nombre de objeto?

Primera forma:

function person(fname, lname, age, eyecolor){
  this.firstname = fname;
  this.lastname = lname;
  this.age = age;
  this.eyecolor = eyecolor;
}

myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");

Segunda forma:

var Robot = {
  metal: "Titanium",
  killAllHumans: function(){
    alert("Exterminate!");
  }
};

Robot.killAllHumans();

Tercera forma: objetos JavaScript con sintaxis de matriz:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }
Jamna
fuente
2
la "var" se usa según el alcance de la variable, define el global o no, búscalo y verás la diferencia.
jackJoe
80
si crea robots homicidas, siempre use var, por favor .. omitiendo los hace mundial
mykhal
9
"var se usa dependiendo del alcance de la variable" - esta es una práctica MALA - debe usarse sin importar en qué alcance estés
treecoder
1
¿Qué pasa con el método Object.create():?
Max
Sería bueno si "como se menciona que las propiedades son variables" se aclaró. Quién es"? ¿Dónde se menciona eso? ¿Puedes citar una cita específica?
user4642212

Respuestas:

181

No hay mejor manera, depende de su caso de uso.

  • Use el modo 1 si desea crear varios objetos similares. En su ejemplo, Person(debe comenzar el nombre con una letra mayúscula) se llama función constructora . Esto es similar a las clases en otros idiomas OO.
  • Use el modo 2 si solo necesita un objeto de un tipo (como un singleton). Si desea que este objeto herede de otro, entonces debe usar una función constructora.
  • Utilice el modo 3 si desea inicializar las propiedades del objeto en función de otras propiedades del mismo o si tiene nombres de propiedad dinámicos.

Actualización: como ejemplos solicitados para la tercera vía.

Propiedades dependientes:

Lo siguiente no funciona como thisno se refiere book. No hay forma de inicializar una propiedad con valores de otras propiedades en un objeto literal:

var book = {
    price: somePrice * discount,
    pages: 500,
    pricePerPage: this.price / this.pages
};

en cambio, podrías hacer:

var book = {
    price: somePrice * discount,
    pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;

Nombres de propiedades dinámicas:

Si el nombre de la propiedad se almacena en alguna variable o se crea mediante alguna expresión, entonces debe usar la notación de corchetes:

var name = 'propertyName';

// the property will be `name`, not `propertyName`
var obj = {
    name: 42
}; 

// same here
obj.name = 42;

// this works, it will set `propertyName`
obj[name] = 42;
Felix Kling
fuente
1
gracias por su respuesta ... ahora entendí su primer punto, podemos usar way1 si queremos algo como esto myFather = new person ("John", "Doe", 50, "blue"); myMother = persona nueva ("gazy", "Doe", 45, "brown"); myBrother = nueva persona ("encuesta", "Doe", 15, "azul");
Jamna
Creo que te refieres a obj [nombre] = 42. ¿Verdad?
Keith Pinson
Me gustaría señalar que las opciones 2 y 3 son prácticamente idénticas, solo que está asignando propiedades después de crear el objeto. Esto es lo que se llama notación literal , porque estás usando un objeto literal para crear tu objeto. Bajo el capó, esto realmente llama "nuevo Object ()". Puede leer más sobre esto aquí: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
dudewad
Para el segundo caso, ¿tendría sentido si utilizáramos el operador de propagación ...para heredar de otro objeto?
6pack kid
114

Hay varias formas de definir una función. Está totalmente basado en su requerimiento. Debajo están los pocos estilos: -

  1. Constructor de objetos
  2. Constructor literal
  3. Función basada
  4. Basado en el prototipo
  5. Función y prototipo basado
  6. Basado en Singleton

Ejemplos:

  1. Constructor de objetos
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. Constructor literal
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. función Constructor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. Prototipo
function Person(){};

Person.prototype.name = "Anand";
  1. Combinación función / prototipo
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. único
var person = new function(){
  this.name = "Anand"
} 

Puedes probarlo en la consola, si tienes alguna confusión.

Anand Deep Singh
fuente
HEY @Alex_Nabu: ya he compartido los ejemplos en mi publicación. Si aún enfrenta algún desafío, actualíceme, lo ayudaré.
Anand Deep Singh
1
¿No tendría más sentido construir cada ejemplo produciendo exactamente la misma var personinstancia al final? por ejemplo, en el constructor de funciones, simplemente podría agregar var person = new Person("Anand"). ¿Y qué pasa con el uso de punto y coma aparentemente aleatorio? : P
cregox
2
Agregaría valor explicando los pros y los contras de cada manera.
RayLoveless
10

No hay "mejor manera" de crear un objeto. Cada forma tiene beneficios dependiendo de su caso de uso.

El patrón de constructor (una función emparejada con el newoperador para invocarlo) ofrece la posibilidad de utilizar la herencia prototípica, mientras que las otras formas no lo hacen. Entonces, si desea la herencia de prototipos, entonces una función de constructor es un buen camino a seguir.

Sin embargo, si desea una herencia prototípica, también puede usarla Object.create, lo que hace que la herencia sea más obvia.

Crear un objeto literal (ej . var obj = {foo: "bar"};:) funciona muy bien si tiene todas las propiedades que desea establecer a mano en el momento de la creación.

Para configurar las propiedades más adelante, la NewObject.property1sintaxis generalmente es preferible a NewObject['property1']si conoce el nombre de la propiedad. Pero este último es útil cuando en realidad no tiene el nombre de la propiedad antes de tiempo (ej NewObject[someStringVar].:).

¡Espero que esto ayude!

jimbo
fuente
6

Supongo que depende de lo que quieras. Para objetos simples, supongo que podría usar los segundos métodos. Cuando tus objetos crecen y planeas usar objetos similares, creo que el primer método sería mejor. De esa manera también puedes extenderlo usando prototipos.

Ejemplo:

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.getCircumference = function() {
    return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
    return Math.PI * this.radius * this.radius;
}

No soy un gran admirador del tercer método, pero es realmente útil para editar propiedades dinámicamente, por ejemplo var foo='bar'; var bar = someObject[foo];.

Daan Wilmer
fuente
3

Hay muchas formas de crear sus objetos en JavaScript. Usar una función de constructor para crear un objeto o notación literal de objeto es usar mucho en JavaScript. Además de crear una instancia de Object y luego agregarle propiedades y métodos, hay tres formas comunes de crear objetos en JavaScript.

Funciones de constructor

Hay funciones de constructor incorporadas que todos podemos usar de vez en cuando, como Date (), Number (), Boolean (), etc., todas las funciones de constructor comienzan con mayúscula, mientras tanto podemos crear una función de constructor personalizada en JavaScript Me gusta esto:

function Box (Width, Height, fill) {  
  this.width = Width;  // The width of the box 
  this.height = Height;  // The height of the box 
  this.fill = true;  // Is it filled or not?
}  

y puede invocarlo, simplemente usando new (), para crear una nueva instancia del constructor, cree algo como a continuación y llame a la función del constructor con parámetros llenos:

var newBox = new Box(8, 12, true);  

Literales de objeto

El uso de literales de objetos es muy utilizado para crear objetos en JavaScript, este es un ejemplo de creación de un objeto simple, puede asignar cualquier cosa a las propiedades de su objeto siempre que estén definidas:

var person = { 
    name: "Alireza",
    surname: "Dezfoolian"
    nose: 1,  
    feet: 2,  
    hands: 2,
    cash: null
};  

Prototipos

Después de crear un Objeto, puede crear un prototipo de más miembros para eso, por ejemplo, agregar color a nuestro Cuadro, podemos hacer esto:

Box.prototype.colour = 'red';
Alireza
fuente
2

Si bien muchas personas aquí dicen que no hay una mejor manera para la creación de objetos, existe una justificación de por qué hay tantas formas de crear objetos en JavaScript, a partir de 2019, y esto tiene que ver con el progreso de JavaScript en las diferentes iteraciones de los lanzamientos de EcmaScript que datan de 1997.

Antes de ECMAScript 5, solo había dos formas de crear objetos: la función constructora o la notación literal (una mejor alternativa al nuevo Object ()). Con la notación de función de constructor, crea un objeto que se puede instanciar en varias instancias (con la nueva palabra clave), mientras que la notación literal entrega un solo objeto, como un singleton.

// constructor function
function Person() {};

// literal notation
var Person = {};

Independientemente del método que utilice, los objetos de JavaScript son simplemente propiedades de pares de valores clave:

// Method 1: dot notation
obj.firstName = 'Bob';

// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';

// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
    value: 'Bob',
    writable: true,
    configurable: true,
    enumerable: false
})

// Method 4: Object.defineProperties
Object.defineProperties(obj, {
  firstName: {
    value: 'Bob',
    writable: true
  },
  lastName: {
    value: 'Smith',
    writable: false
  }
});

En las primeras versiones de JavaScript, la única forma real de imitar la herencia basada en clases era usar funciones de constructor. la función constructora es una función especial que se invoca con la palabra clave 'new'. Por convención, el identificador de la función está en mayúscula, aunque no es obligatorio. Dentro del constructor, nos referimos a la palabra clave 'this' para agregar propiedades al objeto que la función constructora está creando implícitamente. La función constructora devuelve implícitamente el nuevo objeto con las propiedades pobladas a la función de llamada implícitamente, a menos que use explícitamente la palabra clave return y devuelva otra cosa.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.sayName = function(){
        return "My name is " + this.firstName + " " + this.lastName;
    }
} 

var bob = new Person("Bob", "Smith");
bob instanceOf Person // true

Hay un problema con el método sayName. Por lo general, en los lenguajes de programación basados ​​en clases orientadas a objetos, se utilizan clases como fábricas para crear objetos. Cada objeto tendrá sus propias variables de instancia, pero tendrá un puntero a los métodos definidos en el plano de la clase. Desafortunadamente, cuando se usa la función constructora de JavaScript, cada vez que se llama, definirá una nueva propiedad sayName en el objeto recién creado. Por lo tanto, cada objeto tendrá su propia propiedad única sayName. Esto consumirá más recursos de memoria.

Además del aumento de los recursos de memoria, la definición de métodos dentro de la función constructora elimina la posibilidad de herencia. Nuevamente, el método se definirá como una propiedad en el objeto recién creado y ningún otro objeto, por lo que la herencia no puede funcionar como. Por lo tanto, JavaScript proporciona la cadena de prototipos como una forma de herencia, haciendo de JavaScript un lenguaje prototípico.

Si tiene un padre y un padre comparte muchas propiedades de un hijo, entonces el hijo debe heredar esas propiedades. Antes de ES5, se logró de la siguiente manera:

function Parent(eyeColor, hairColor) {
    this.eyeColor = eyeColor;
    this.hairColor = hairColor;
}

Parent.prototype.getEyeColor = function() {
  console.log('has ' + this.eyeColor);
}

Parent.prototype.getHairColor = function() {
  console.log('has ' + this.hairColor);
}

function Child(firstName, lastName) {
  Parent.call(this, arguments[2], arguments[3]);
  this.firstName = firstName;
  this.lastName = lastName;
}

Child.prototype = Parent.prototype;

var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair

La forma en que utilizamos la cadena de prototipos anterior tiene una peculiaridad. Dado que el prototipo es un enlace en vivo, al cambiar la propiedad de un objeto en la cadena del prototipo, también cambiaría la misma propiedad de otro objeto. Obviamente, cambiar el método heredado de un niño no debería cambiar el método de los padres. Object.create resolvió este problema utilizando un polyfill. Por lo tanto, con Object.create, puede modificar de forma segura la propiedad de un niño en la cadena del prototipo sin afectar la misma propiedad del padre en la cadena del prototipo.

ECMAScript 5 introdujo Object.create para resolver el error mencionado anteriormente en la función de constructor para la creación de objetos. El método Object.create () CREA un nuevo objeto, utilizando un objeto existente como prototipo del objeto recién creado. Como se crea un nuevo objeto, ya no tiene el problema de que la modificación de la propiedad secundaria en la cadena prototipo modificará la referencia del padre a esa propiedad en la cadena.

var bobSmith = {
    firstName: "Bob",
    lastName: "Smith",
    sayName: function(){
      return "My name is " + this.firstName + " " + this.lastName;
    }
}

var janeSmith = Object.create(bobSmith, {
    firstName : {  value: "Jane" }
})

console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.

Antes de ES6, aquí había un patrón de creación común para utilizar constructores de funciones y Object.create:

const View = function(element){
  this.element = element;
}

View.prototype = {
  getElement: function(){
    this.element
  }
}

const SubView = function(element){
  View.call(this, element);
}

SubView.prototype = Object.create(View.prototype);

Ahora Object.create junto con las funciones de constructor se han usado ampliamente para la creación y herencia de objetos en JavaScript. Sin embargo, ES6 introdujo el concepto de clases, que son principalmente azúcar sintáctica sobre la herencia basada en prototipos existente de JavaScript. La sintaxis de clase no introduce un nuevo modelo de herencia orientado a objetos a JavaScript. Por lo tanto, JavaScript sigue siendo un lenguaje prototípico.

Las clases de ES6 hacen la herencia mucho más fácil. Ya no tenemos que copiar manualmente las funciones prototipo de la clase principal y restablecer el constructor de la clase secundaria.

// create parent class
class Person {
  constructor (name) {
    this.name = name;
  }
}

// create child class and extend our parent class
class Boy extends Person {
  constructor (name, color) {
    // invoke our parent constructor function passing in any required parameters
    super(name);

    this.favoriteColor = color;
  }
}

const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue

Con todo, estas 5 estrategias diferentes de creación de objetos en JavaScript coincidieron con la evolución del estándar EcmaScript.

Donato
fuente
0

Por supuesto, hay una mejor manera. Los objetos en JavaScript tienen propiedades enumerables y no enumerables.

var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]

En el ejemplo anterior, puede ver que un objeto vacío tiene propiedades.

Ok, primero veamos cuál es la mejor manera:

var new_object = Object.create(null)

new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc

console.log("toString" in new_object) //=> false

En el ejemplo anterior, el registro generará falso.

Ahora veamos por qué las otras formas de creación de objetos son incorrectas.

//Object constructor
var object = new Object();

console.log("toString" in object); //=> true

//Literal constructor
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 

console.log("toString" in person); //=> true

//function Constructor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
}

var person = new Person ('landi')

console.log("toString" in person); //=> true

//Prototype
function Person(){};

Person.prototype.name = "Anand";

console.log("toString" in person); //=> true

//Function/Prototype combination
function Person2(name){
  this.name = name;
} 

Person2.prototype.getName = function(){
  return this.name
}

var person2 = new Person2('Roland')

console.log("toString" in person2) //=> true

Como puede ver arriba, todos los ejemplos se registran como verdaderos, lo que significa que si tiene un caso, tiene un for inbucle para ver si el objeto tiene una propiedad, probablemente lo llevará a resultados incorrectos.

Tenga en cuenta que la mejor manera no es fácil. Debe definir todas las propiedades del objeto línea por línea. Las otras formas son más fáciles y tendrán menos código para crear un objeto, pero en algunos casos debe tener en cuenta. Por cierto, siempre uso las "otras formas" y una solución a la advertencia anterior si no usa la mejor manera es:

 for (var property in new_object) {
  if (new_object.hasOwnProperty(property)) {
    // ... this is an own property
  }
 }
roli roli
fuente
0

Principalmente hay 3 formas de crear objetos:

El más simple está usando literales de objeto .

const myObject = {}

Aunque este método es el más simple pero tiene una desventaja, es decir, si su objeto tiene un comportamiento (funciones en él), en el futuro, si desea realizar algún cambio, deberá cambiarlo en todos los objetos .

Entonces, en ese caso, es mejor usar las funciones de fábrica o de constructor (cualquiera que le guste)

Las funciones de fábrica son aquellas funciones que devuelven un objeto.

function factoryFunc(exampleValue){
   return{
      exampleProperty: exampleValue 
   }
}

Las funciones de constructor son aquellas funciones que asignan propiedades a los objetos usando "esta" palabra clave.

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
Shivam Bansal
fuente