Welcher Weg eignet sich am besten zum Erstellen eines Objekts in JavaScript? Ist `var` vor einer Objekteigenschaft notwendig?

177

Bisher habe ich drei Möglichkeiten zum Erstellen eines Objekts in JavaScript gesehen. Welcher Weg eignet sich am besten zum Erstellen eines Objekts und warum?

Ich habe auch gesehen, dass in all diesen Beispielen das Schlüsselwort varnicht vor einer Eigenschaft verwendet wird - warum? Ist es nicht erforderlich, varvor dem Namen einer Eigenschaft zu deklarieren, dass Eigenschaften Variablen sind?

In der zweiten und dritten Art ist der Name des Objekts in Großbuchstaben, während in erster Linie der Name des Objekts in Kleinbuchstaben ist. Welchen Fall sollten wir für einen Objektnamen verwenden?

Erster Weg:

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

Zweiter Weg:

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

Robot.killAllHumans();

Dritter Weg - JavaScript-Objekte mit Array-Syntax:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }
Jamna
quelle
2
Das "var" wird abhängig vom Umfang der Variablen verwendet. Es definiert das globale oder nicht, durchsucht es und Sie werden den Unterschied sehen.
JackJoe
80
Wenn Sie var
Mordroboter
9
"var wird abhängig vom Umfang der Variablen verwendet" - dies ist eine schlechte Praxis - es sollte verwendet werden, egal in welchem ​​Bereich Sie sich befinden
treecoder
1
Was ist mit der Methode : Object.create()?
Max
Es wäre schön, wenn „wie erwähnt, dass Eigenschaften Variablen sind“ geklärt würde. Wer ist es"? Wo wird das erwähnt? Können Sie ein bestimmtes Zitat zitieren?
user4642212

Antworten:

181

Es gibt keinen besten Weg, es hängt von Ihrem Anwendungsfall ab.

  • Verwenden Sie Weg 1, wenn Sie mehrere ähnliche Objekte erstellen möchten. In Ihrem Beispiel Person(Sie sollten den Namen mit einem Großbuchstaben beginnen) wird die Konstruktorfunktion genannt . Dies ähnelt Klassen in anderen OO-Sprachen.
  • Verwenden Sie Weg 2, wenn Sie nur ein Objekt einer Art benötigen (wie einen Singleton). Wenn Sie möchten, dass dieses Objekt von einem anderen erbt, müssen Sie jedoch eine Konstruktorfunktion verwenden.
  • Verwenden Sie Methode 3, wenn Sie Eigenschaften des Objekts in Abhängigkeit von anderen Eigenschaften des Objekts initialisieren möchten oder wenn Sie dynamische Eigenschaftsnamen haben.

Update: Wie angeforderte Beispiele für den dritten Weg.

Abhängige Eigenschaften:

Die folgende funktioniert nicht thisnicht nicht verweisen book. Es gibt keine Möglichkeit, eine Eigenschaft mit Werten anderer Eigenschaften in einem Objektliteral zu initialisieren:

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

Stattdessen könnten Sie Folgendes tun:

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

Dynamische Eigenschaftsnamen:

Wenn der Eigenschaftsname in einer Variablen gespeichert oder durch einen Ausdruck erstellt wird, müssen Sie die Klammernotation verwenden:

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
quelle
1
danke für deine Antwort ... jetzt habe ich deinen ersten Punkt verstanden, den wir way1 verwenden können, wenn wir so etwas wollen myFather = neue Person ("John", "Doe", 50, "blue"); myMother = neue Person ("gazy", "Doe", 45, "brown"); myBrother = neue Person ("Umfrage", "Doe", 15, "Blau");
Jamna
Ich denke du meinst obj [Name] = 42. Richtig?
Keith Pinson
Ich möchte darauf hinweisen, dass die Optionen 2 und 3 praktisch identisch sind, nur dass Sie Eigenschaften zuweisen, nachdem Sie das Objekt erstellt haben. Das ist , was die genannte wörtliche Notation , weil Sie eine verwenden Objektliteral Ihr Objekt zu erstellen. Unter der Haube nennt dies tatsächlich "neues Objekt ()". Sie können mehr darüber hier lesen: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
dudewad
Wäre es für den zweiten Fall sinnvoll, wenn wir den Spread-Operator verwenden würden ..., um von einem anderen Objekt zu erben?
6pack Kind
114

Es gibt verschiedene Möglichkeiten, eine Funktion zu definieren. Es basiert vollständig auf Ihrer Anforderung. Nachfolgend einige Stile: -

  1. Objektkonstruktor
  2. Wörtlicher Konstruktor
  3. Funktionsbasiert
  4. Protoype basiert
  5. Funktions- und prototypbasiert
  6. Singleton basiert

Beispiele:

  1. Objektkonstruktor
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. Wörtlicher Konstruktor
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. Funktionskonstruktor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. Prototyp
function Person(){};

Person.prototype.name = "Anand";
  1. Funktions- / Prototypkombination
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. Singleton
var person = new function(){
  this.name = "Anand"
} 

Sie können es auf der Konsole versuchen, wenn Sie Verwirrung haben.

Anand Deep Singh
quelle
HEy @Alex_Nabu - Ich habe die Beispiele bereits in meinem Beitrag geteilt. Wenn Sie immer noch vor Herausforderungen stehen, aktualisieren Sie mich bitte. Ich werde Ihnen helfen.
Anand Deep Singh
1
Wäre es nicht sinnvoller, jedes Beispiel zu erstellen, var persondas am Ende genau dieselbe Instanz liefert ? Zum Beispiel im Funktionskonstruktor können Sie einfach hinzufügen var person = new Person("Anand"). und was ist mit der scheinbar zufälligen Verwendung von Semikolons los? : P
Cregox
2
Es würde einen Mehrwert bieten, der die Vor- und Nachteile der einzelnen Wege erklärt.
RayLoveless
10

Es gibt keinen "besten Weg", ein Objekt zu erstellen. Jeder Weg hat je nach Anwendungsfall Vorteile.

Das Konstruktormuster (eine Funktion, die mit dem newOperator gepaart ist , um es aufzurufen) bietet die Möglichkeit, die prototypische Vererbung zu verwenden, während die anderen Methoden dies nicht tun. Wenn Sie also eine prototypische Vererbung wünschen, ist eine Konstruktorfunktion ein guter Weg.

Wenn Sie jedoch eine prototypische Vererbung wünschen, können Sie diese auch verwenden Object.create, wodurch die Vererbung offensichtlicher wird.

Das Erstellen eines Objektliteral (z. var obj = {foo: "bar"};B. :) funktioniert hervorragend, wenn Sie zum Zeitpunkt der Erstellung über alle Eigenschaften verfügen, die Sie festlegen möchten.

Zum späteren Festlegen von Eigenschaften ist die NewObject.property1Syntax im Allgemeinen vorzuziehen, NewObject['property1']wenn Sie den Eigenschaftsnamen kennen. Letzteres ist jedoch nützlich, wenn Sie den Namen der Eigenschaft nicht im Voraus haben (z. B. :) NewObject[someStringVar].

Hoffe das hilft!

Jimbo
quelle
6

Ich denke, es hängt davon ab, was Sie wollen. Für einfache Objekte könnten Sie die zweite Methode verwenden. Wenn Ihre Objekte größer werden und Sie ähnliche Objekte verwenden möchten, ist die erste Methode wahrscheinlich besser. Auf diese Weise können Sie es auch mit Prototypen erweitern.

Beispiel:

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

Ich bin kein großer Fan der dritten Methode, aber sie ist zum Beispiel sehr nützlich, um Eigenschaften dynamisch zu bearbeiten var foo='bar'; var bar = someObject[foo];.

Daan Wilmer
quelle
3

Es gibt viele Möglichkeiten, Ihre Objekte in JavaScript zu erstellen. Die Verwendung einer Konstruktorfunktion zum Erstellen eines Objekts oder einer Objektliteralnotation verwendet viel in JavaScript. Wenn Sie eine Instanz von Object erstellen und anschließend Eigenschaften und Methoden hinzufügen, gibt es drei gängige Methoden zum Erstellen von Objekten in JavaScript.

Konstruktorfunktionen

Es gibt integrierte Konstruktorfunktionen, die wir alle von Zeit zu Zeit verwenden können, wie Date (), Number (), Boolean () usw. Alle Konstruktorfunktionen beginnen mit Großbuchstaben. In der Zwischenzeit können wir benutzerdefinierte Konstruktorfunktionen in JavaScript erstellen so was:

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

und Sie können es einfach mit new () aufrufen, um eine neue Instanz des Konstruktors zu erstellen, etwas wie das folgende erstellen und die Konstruktorfunktion mit gefüllten Parametern aufrufen:

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

Objektliterale

Die Verwendung von Objektliteralen wird häufig beim Erstellen von Objekten in JavaScript verwendet. Dies ist ein Beispiel für das Erstellen eines einfachen Objekts. Sie können Ihren Objekteigenschaften alles zuweisen, solange sie definiert sind:

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

Prototyp entwickeln

Nachdem Sie ein Objekt erstellt haben, können Sie weitere Elemente als Prototyp erstellen, z. B. indem Sie unserer Box Farbe hinzufügen. Wir können dies tun:

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

Während viele Leute hier sagen, dass es keinen besten Weg für die Objekterstellung gibt, gibt es eine Begründung dafür, warum es ab 2019 so viele Möglichkeiten gibt, Objekte in JavaScript zu erstellen, und dies hat mit dem Fortschritt von JavaScript über die verschiedenen Iterationen zu tun von EcmaScript-Veröffentlichungen aus dem Jahr 1997.

Vor ECMAScript 5 gab es nur zwei Möglichkeiten, Objekte zu erstellen: die Konstruktorfunktion oder die Literalnotation (eine bessere Alternative zu new Object ()). Mit der Konstruktorfunktionsnotation erstellen Sie ein Objekt, das in mehrere Instanzen instanziiert werden kann (mit dem neuen Schlüsselwort), während die Literalnotation ein einzelnes Objekt wie einen Singleton liefert.

// constructor function
function Person() {};

// literal notation
var Person = {};

Unabhängig von der von Ihnen verwendeten Methode sind JavaScript-Objekte einfach Eigenschaften von Schlüsselwertpaaren:

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

In früheren Versionen von JavaScript bestand die einzige Möglichkeit, die klassenbasierte Vererbung nachzuahmen, in der Verwendung von Konstruktorfunktionen. Die Konstruktorfunktion ist eine spezielle Funktion, die mit dem Schlüsselwort 'new' aufgerufen wird. Konventionell wird die Funktionskennung großgeschrieben, albiet ist sie nicht erforderlich. Innerhalb des Konstruktors verweisen wir auf das Schlüsselwort 'this', um dem Objekt, das die Konstruktorfunktion implizit erstellt, Eigenschaften hinzuzufügen. Die Konstruktorfunktion gibt das neue Objekt mit den aufgefüllten Eigenschaften implizit implizit an die aufrufende Funktion zurück, es sei denn, Sie verwenden explizit das Schlüsselwort return und geben etwas anderes zurück.

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

Es liegt ein Problem mit der sayName-Methode vor. In objektorientierten klassenbasierten Programmiersprachen verwenden Sie normalerweise Klassen als Fabriken, um Objekte zu erstellen. Jedes Objekt verfügt über eigene Instanzvariablen, jedoch über einen Zeiger auf die im Klassenentwurf definierten Methoden. Wenn Sie die Konstruktorfunktion von JavaScript verwenden, wird bei jedem Aufruf eine neue sayName-Eigenschaft für das neu erstellte Objekt definiert. Jedes Objekt verfügt also über eine eigene Eigenschaft sayName. Dies verbraucht mehr Speicherressourcen.

Neben der Erhöhung der Speicherressourcen wird durch die Definition von Methoden innerhalb der Konstruktorfunktion die Möglichkeit der Vererbung ausgeschlossen. Auch hier wird die Methode als Eigenschaft für das neu erstellte Objekt und für kein anderes Objekt definiert, sodass die Vererbung nicht wie folgt funktionieren kann. Daher stellt JavaScript die Prototypenkette als eine Form der Vererbung bereit, wodurch JavaScript zu einer prototypischen Sprache wird.

Wenn Sie ein Elternteil haben und ein Elternteil viele Eigenschaften eines Kindes teilt, sollte das Kind diese Eigenschaften erben. Vor ES5 wurde dies wie folgt erreicht:

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

Die Art und Weise, wie wir die obige Prototypenkette verwendet haben, ist eigenartig. Da der Prototyp ein Live-Link ist, würden Sie durch Ändern der Eigenschaft eines Objekts in der Prototypkette auch dieselbe Eigenschaft eines anderen Objekts ändern. Das Ändern der geerbten Methode eines Kindes sollte natürlich nicht die Methode des Elternteils ändern. Object.create hat dieses Problem mithilfe einer Polyfüllung behoben. Mit Object.create können Sie also die Eigenschaft eines Kindes in der Prototypkette sicher ändern, ohne die gleiche Eigenschaft des Elternteils in der Prototypkette zu beeinflussen.

ECMAScript 5 führte Object.create ein, um den oben genannten Fehler in der Konstruktorfunktion für die Objekterstellung zu beheben. Die Object.create () -Methode ERSTELLT ein neues Objekt, wobei ein vorhandenes Objekt als Prototyp des neu erstellten Objekts verwendet wird. Da ein neues Objekt erstellt wird, besteht kein Problem mehr, bei dem durch Ändern der untergeordneten Eigenschaft in der Prototypkette der Verweis des übergeordneten Elements auf diese Eigenschaft in der Kette geändert wird.

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.

Vor ES6 gab es hier ein allgemeines Erstellungsmuster für die Verwendung von Funktionskonstruktoren und 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);

Jetzt wurde Object.create in Verbindung mit Konstruktorfunktionen häufig für die Objekterstellung und -vererbung in JavaScript verwendet. ES6 führte jedoch das Konzept von Klassen ein, bei denen es sich in erster Linie um syntaktischen Zucker gegenüber der vorhandenen prototypbasierten Vererbung von JavaScript handelt. Die Klassensyntax führt kein neues objektorientiertes Vererbungsmodell in JavaScript ein. Somit bleibt JavaScript eine prototypische Sprache.

ES6-Klassen erleichtern die Vererbung erheblich. Wir müssen die Prototypfunktionen der übergeordneten Klasse nicht mehr manuell kopieren und den Konstruktor der untergeordneten Klasse zurücksetzen.

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

Insgesamt fielen diese 5 verschiedenen Strategien der Objekterstellung in JavaScript mit der Entwicklung des EcmaScript-Standards zusammen.

Donato
quelle
0

Natürlich gibt es einen besten Weg. Objekte in Javascript haben aufzählbare und nicht aufzählbare Eigenschaften.

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

Im obigen Beispiel sehen Sie, dass ein leeres Objekt tatsächlich Eigenschaften hat.

Ok, zuerst wollen wir sehen, welcher der beste Weg ist:

var new_object = Object.create(null)

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

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

Im obigen Beispiel gibt das Protokoll false aus.

Lassen Sie uns nun sehen, warum die anderen Objekterstellungsmethoden falsch sind.

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

Wie Sie oben sehen können, protokollieren alle Beispiele true. Wenn Sie also eine for inSchleife haben, um festzustellen, ob das Objekt eine Eigenschaft hat, führt dies wahrscheinlich zu falschen Ergebnissen.

Beachten Sie, dass dies am besten nicht einfach ist. Sie müssen alle Eigenschaften des Objekts zeilenweise definieren. Die anderen Methoden sind einfacher und enthalten weniger Code zum Erstellen eines Objekts. In einigen Fällen müssen Sie sich jedoch bewusst sein. Ich benutze übrigens immer die "anderen Wege" und eine Lösung für die obige Warnung, wenn Sie nicht den besten Weg benutzen, ist:

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

Hauptsächlich gibt es 3 Möglichkeiten, Objekte zu erstellen:

Am einfachsten ist die Verwendung von Objektliteralen .

const myObject = {}

Obwohl diese Methode die einfachste ist, aber einen Nachteil hat, dh wenn Ihr Objekt Verhalten aufweist (Funktionen darin), müssen Sie es in Zukunft in allen Objekten ändern, wenn Sie Änderungen daran vornehmen möchten .

In diesem Fall ist es besser, Factory- oder Konstruktorfunktionen zu verwenden (jeder, den Sie mögen).

Factory-Funktionen sind Funktionen, die ein object.eg- zurückgeben.

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

Konstruktorfunktionen sind Funktionen, die Objekten mit "this" keyword.eg- Eigenschaften zuweisen.

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