Qual è il modo migliore per creare un oggetto in JavaScript? `Var` è necessario prima di una proprietà dell'oggetto?


177

Finora ho visto tre modi per creare un oggetto in JavaScript. Qual è il modo migliore per creare un oggetto e perché?

Ho anche visto che in tutti questi esempi la parola chiave varnon viene utilizzata prima di una proprietà - perché? Non è necessario dichiarare varprima del nome di una proprietà poiché ha menzionato che le proprietà sono variabili?

Nel secondo e terzo modo, il nome dell'oggetto è in maiuscolo mentre nel primo modo il nome dell'oggetto è in minuscolo. Quale caso dovremmo usare per un nome di oggetto?

Primo modo:

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.");

Secondo modo:

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

Robot.killAllHumans();

Terzo modo: oggetti JavaScript che utilizzano la sintassi dell'array:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }

2
il "var" viene utilizzato a seconda dell'ambito della variabile, definisce il globale o no, cercalo e vedrai la differenza.
jackJoe,

80
se crei robot omicidi, var
usali

9
"var è usato a seconda dell'ambito della variabile" - questa è cattiva pratica - dovrebbe essere usato indipendentemente dall'ambito in cui ti trovi
treecoder

1
Che dire del metodo Object.create():?
Max

Sarebbe bello se "come dicesse che le proprietà sono variabili" fosse chiarito. Chi è"? Dov'è menzionato? Puoi citare un preventivo specifico?
user4642212

Risposte:


181

Non esiste un modo migliore , dipende dal tuo caso d'uso.

  • Utilizzare il modo 1 se si desidera creare più oggetti simili. Nel tuo esempio, Person(dovresti iniziare il nome con una lettera maiuscola) è chiamata la funzione di costruzione . Questo è simile alle lezioni in altre lingue OO.
  • Utilizzare il modo 2 se è necessario solo un oggetto di un tipo (come un singleton). Se vuoi che questo oggetto erediti da un altro, allora devi usare una funzione di costruzione.
  • Utilizzare il metodo 3 se si desidera inizializzare le proprietà dell'oggetto in base ad altre proprietà di esso o se si dispone di nomi di proprietà dinamici.

Aggiornamento: come esempi richiesti per la terza via.

Proprietà dipendenti:

Quanto segue non funziona in quanto thisnon si riferisce a book. Non è possibile inizializzare una proprietà con valori di altre proprietà in un oggetto letterale:

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

invece, potresti fare:

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

Nomi di proprietà dinamici:

Se il nome della proprietà è memorizzato in qualche variabile o creato tramite qualche espressione, allora devi usare la notazione parentesi:

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;

1
grazie per la tua risposta ... ora ho capito il tuo primo punto, possiamo usare way1 se vogliamo qualcosa del genere myFather = new person ("John", "Doe", 50, "blue"); myMother = new person ("gazy", "Doe", 45, "brown"); myBrother = nuova persona ("sondaggio", "Doe", 15, "blu");
Jamna,

Penso che intendi obj [nome] = 42. Giusto?
Keith Pinson,

Vorrei sottolineare che le opzioni 2 e 3 sono praticamente identiche, solo che si stanno assegnando proprietà dopo aver creato l'oggetto. Questo è ciò che viene chiamato notazione letterale , perché stai usando un oggetto letterale per creare il tuo oggetto. Sotto il cofano, questo in realtà chiama "new Object ()". Puoi leggere di più qui: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
dudewad,

Per il secondo caso, avrebbe senso se usassimo l'operatore spread ...per ereditare da un altro oggetto?
6pacco bambino

114

Esistono vari modi per definire una funzione. È totalmente basato sulle vostre esigenze. Di seguito sono riportati alcuni stili: -

  1. Costruttore di oggetti
  2. Costruttore letterale
  3. Basato su funzioni
  4. Basato su prototipo
  5. Basato su funzione e prototipo
  6. Basato su Singleton

Esempi:

  1. Costruttore di oggetti
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. Costruttore letterale
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. Funzione Costruttore
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. Prototipo
function Person(){};

Person.prototype.name = "Anand";
  1. Combinazione funzione / prototipo
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. Singleton
var person = new function(){
  this.name = "Anand"
} 

Puoi provarlo su console, se hai qualche confusione.


HEy @Alex_Nabu - Ho già condiviso gli esempi nel mio post. Se hai ancora problemi, ti prego di aggiornarmi, ti aiuterò.
Anand Deep Singh,

1
non avrebbe più senso costruire ogni esempio producendo esattamente la stessa var personistanza alla fine? ad esempio nel costruttore della funzione potresti semplicemente aggiungere var person = new Person("Anand"). e che succede con l'uso di punti e virgola apparentemente casuali? : P
cregox,

2
Aggiungerebbe valore spiegando pro e contro di ogni modo.
RayLoveless,

10

Non esiste un "modo migliore" per creare un oggetto. Ogni modo ha vantaggi a seconda del caso d'uso.

Il modello del costruttore (una funzione accoppiata con l' newoperatore per invocarlo) offre la possibilità di utilizzare l'eredità prototipale, mentre gli altri modi non lo fanno. Quindi, se si desidera l'eredità prototipale, una funzione di costruzione è una buona strada da percorrere.

Tuttavia, se si desidera l'ereditarietà prototipale, è possibile utilizzare anche Object.create, il che rende l'eredità più ovvia.

La creazione di un oggetto letterale (es:) var obj = {foo: "bar"};funziona benissimo se ti capita di avere tutte le proprietà che desideri mettere a portata di mano al momento della creazione.

Per impostare le proprietà in un secondo momento, la NewObject.property1sintassi è generalmente preferibile NewObject['property1']se si conosce il nome della proprietà. Quest'ultimo è utile quando in realtà non si ha in anticipo il nome della proprietà (es:) NewObject[someStringVar].

Spero che questo ti aiuti!


6

Immagino che dipenda da quello che vuoi. Per oggetti semplici, immagino che potresti usare il secondo metodo. Quando i tuoi oggetti diventano più grandi e hai intenzione di utilizzare oggetti simili, immagino che il primo metodo sarebbe migliore. In questo modo puoi anche estenderlo usando i prototipi.

Esempio:

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;
}

Non sono un grande fan del terzo metodo, ma è davvero utile per modificare dinamicamente le proprietà, ad esempio var foo='bar'; var bar = someObject[foo];.


3

Esistono molti modi per creare i tuoi oggetti in JavaScript. L'uso di una funzione di costruzione per creare un oggetto o una notazione letterale dell'oggetto sta usando molto in JavaScript. Inoltre, creando un'istanza di Object e quindi aggiungendo proprietà e metodi, esistono tre modi comuni per creare oggetti in JavaScript.

Funzioni del costruttore

Ci sono funzioni di costruzione integrate che tutti noi possiamo usarle di volta in volta, come Date (), Number (), Boolean () ecc., Tutte le funzioni di costruzione iniziano con la lettera maiuscola, nel frattempo possiamo creare una funzione di costruzione personalizzata in JavaScript come questo:

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?
}  

e puoi invocarlo, semplicemente usando new (), per creare una nuova istanza del costruttore, creare qualcosa come sotto e chiamare la funzione di costruzione con parametri riempiti:

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

Oggetti letterali

Utilizzando i letterali di oggetti sono molto usati la creazione di casi in JavaScript, questo esempio di creazione di un oggetto semplice, è possibile assegnare qualsiasi cosa alle proprietà dell'oggetto purché siano definite:

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

Prototipazione

Dopo aver creato un oggetto, puoi prototipare più membri a questo, ad esempio aggiungendo colore alla nostra scatola, possiamo farlo:

Box.prototype.colour = 'red';

2

Mentre molte persone qui affermano che non esiste un modo migliore per la creazione di oggetti, c'è una logica del perché ci sono così tanti modi per creare oggetti in JavaScript, a partire dal 2019, e questo ha a che fare con l'avanzamento di JavaScript sulle diverse iterazioni delle versioni EcmaScript risalenti al 1997.

Prima di ECMAScript 5, c'erano solo due modi per creare oggetti: la funzione di costruzione o la notazione letterale (una migliore alternativa a new Object ()). Con la notazione della funzione di costruzione si crea un oggetto che può essere istanziato in più istanze (con la nuova parola chiave), mentre la notazione letterale fornisce un singolo oggetto, come un singleton.

// constructor function
function Person() {};

// literal notation
var Person = {};

Indipendentemente dal metodo utilizzato, gli oggetti JavaScript sono semplicemente proprietà delle coppie chiave-valore:

// 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
  }
});

Nelle prime versioni di JavaScript, l'unico vero modo per imitare l'eredità basata su classi era usare le funzioni di costruzione. la funzione di costruzione è una funzione speciale che viene invocata con la parola chiave "new". Per convenzione, l'identificatore di funzione è in maiuscolo, albiet non è richiesto. All'interno del costruttore, ci riferiamo alla parola chiave "this" per aggiungere proprietà all'oggetto che la funzione di costruzione sta implicitamente creando. La funzione di costruzione restituisce implicitamente il nuovo oggetto con le proprietà popolate in modo implicito alla funzione di chiamata, a meno che non si usi esplicitamente la parola chiave return e si restituisca qualcos'altro.

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

Si è verificato un problema con il metodo sayName. In genere, nei linguaggi di programmazione basati su classi orientate agli oggetti, le classi vengono utilizzate come fabbriche per creare oggetti. Ogni oggetto avrà le sue variabili di istanza, ma avrà un puntatore ai metodi definiti nel modello di classe. Sfortunatamente, quando si utilizza la funzione di costruzione JavaScript, ogni volta che viene chiamato, definirà una nuova proprietà sayName sull'oggetto appena creato. Quindi ogni oggetto avrà la sua proprietà unica sayName. Ciò consumerà più risorse di memoria.

Oltre all'aumento delle risorse di memoria, la definizione di metodi all'interno della funzione di costruzione elimina la possibilità di ereditarietà. Ancora una volta, il metodo verrà definito come una proprietà sull'oggetto appena creato e nessun altro oggetto, quindi l'ereditarietà non può funzionare come. Pertanto, JavaScript fornisce la catena di prototipi come una forma di eredità, rendendo JavaScript un linguaggio prototipo.

Se hai un genitore e un genitore condivide molte proprietà di un figlio, il figlio dovrebbe ereditare tali proprietà. Prima di ES5, è stato realizzato come segue:

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

Il modo in cui abbiamo utilizzato la catena di prototipi sopra ha una stranezza. Poiché il prototipo è un collegamento attivo, modificando la proprietà di un oggetto nella catena del prototipo, cambieresti anche la stessa proprietà di un altro oggetto. Ovviamente, cambiare il metodo ereditato da un bambino non dovrebbe cambiare il metodo del genitore. Object.create ha risolto questo problema utilizzando un polyfill. Pertanto, con Object.create, è possibile modificare in modo sicuro la proprietà di un bambino nella catena del prototipo senza influire sulla stessa proprietà del genitore nella catena del prototipo.

ECMAScript 5 ha introdotto Object.create per risolvere il suddetto errore nella funzione di costruzione per la creazione di oggetti. Il metodo Object.create () CREA un nuovo oggetto, utilizzando un oggetto esistente come prototipo dell'oggetto appena creato. Poiché viene creato un nuovo oggetto, non si verifica più il problema in cui la modifica della proprietà figlio nella catena di prototipi modificherà il riferimento del genitore a quella proprietà nella catena.

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.

Prima di ES6, ecco un modello di creazione comune per utilizzare i costruttori di funzioni e 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);

Ora Object.create associato a funzioni di costruzione sono stati ampiamente utilizzati per la creazione e l'ereditarietà di oggetti in JavaScript. Tuttavia, ES6 ha introdotto il concetto di classi, che sono principalmente zucchero sintattico sull'eredità esistente basata su prototipo di JavaScript. La sintassi della classe non introduce un nuovo modello di ereditarietà orientato agli oggetti in JavaScript. Pertanto, JavaScript rimane un linguaggio prototipo.

Le classi ES6 rendono l'ereditarietà molto più semplice. Non è più necessario copiare manualmente le funzioni prototipo della classe genitore e ripristinare il costruttore della classe figlio.

// 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

Tutto sommato, queste 5 diverse strategie di creazione di oggetti in JavaScript hanno coinciso con l'evoluzione dello standard EcmaScript.


0

Naturalmente c'è un modo migliore. Gli oggetti in JavaScript hanno proprietà enumerabili e non numerabili.

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

Nell'esempio sopra puoi vedere che un oggetto vuoto ha effettivamente proprietà.

Ok, prima vediamo qual è il modo migliore:

var new_object = Object.create(null)

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

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

Nell'esempio sopra il registro produrrà false.

Ora vediamo perché gli altri modi di creazione degli oggetti non sono corretti.

//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

Come puoi vedere sopra, tutti gli esempi registrano true. Ciò significa che se hai un caso in cui hai un for inciclo per vedere se l'oggetto ha una proprietà probabilmente ti porterà a risultati sbagliati.

Nota che il modo migliore non è facile. Devi definire tutte le proprietà dell'oggetto riga per riga. Gli altri modi sono più facili e avranno meno codice per creare un oggetto, ma devi essere consapevole in alcuni casi. Uso sempre gli "altri modi" e una soluzione all'avvertimento sopra se non usi il modo migliore è:

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

0

Principalmente ci sono 3 modi per creare oggetti:

Il più semplice è usare letterali di oggetti .

const myObject = {}

Anche se questo metodo è il più semplice ma presenta uno svantaggio, ad esempio se il tuo oggetto ha un comportamento (funziona al suo interno), in futuro se vuoi apportare delle modifiche dovresti cambiarlo in tutti gli oggetti .

Quindi in quel caso è meglio usare le funzioni Factory o Costruttore (chiunque ti piaccia)

Le funzioni di fabbrica sono quelle funzioni che restituiscono un oggetto.

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

Le funzioni del costruttore sono quelle funzioni che assegnano proprietà agli oggetti usando "this" keyword.eg-

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.