Cara mana yang terbaik untuk membuat objek dalam JavaScript? Apakah `var` diperlukan sebelum properti objek?

177

Sejauh ini saya melihat tiga cara untuk membuat objek dalam JavaScript. Cara mana yang terbaik untuk membuat objek dan mengapa?

Saya juga melihat bahwa dalam semua contoh ini kata kunci vartidak digunakan sebelum properti - mengapa? Apakah tidak perlu menyatakan varsebelum nama properti karena disebutkan bahwa properti adalah variabel?

Dalam cara kedua dan ketiga, nama objek dalam huruf besar sedangkan dalam cara pertama nama objek dalam huruf kecil. Kasing apa yang harus kita gunakan untuk nama objek?

Cara pertama:

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

Cara kedua:

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

Robot.killAllHumans();

Cara ketiga - objek JavaScript menggunakan sintaksis array:

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }
Jamna
sumber
2
"var" digunakan tergantung pada ruang lingkup variabel, itu menentukan global atau tidak, cari dan Anda akan melihat perbedaannya.
jackJoe
80
jika Anda membuat robot pembunuh, selalu gunakan var, tolong .. dengan menghilangkannya menjadikannya global
mykhal
9
"var digunakan tergantung pada ruang lingkup variabel" - ini adalah praktik buruk - harus digunakan tidak peduli apa pun ruang lingkup Anda
treecoder
1
Bagaimana dengan metode ini Object.create():?
Maks
Akan lebih baik jika "seperti yang disebutkan bahwa properti adalah variabel" diklarifikasi. Siapa ini"? Di mana itu disebutkan? Bisakah Anda mengutip kutipan tertentu?
user4642212

Jawaban:

181

Tidak ada cara terbaik , itu tergantung pada kasus penggunaan Anda.

  • Gunakan cara 1 jika Anda ingin membuat beberapa objek serupa. Dalam contoh Anda, Person(Anda harus memulai nama dengan huruf besar) disebut fungsi konstruktor . Ini mirip dengan kelas dalam bahasa OO lainnya.
  • Gunakan cara 2 jika Anda hanya membutuhkan satu objek sejenis (seperti singleton). Jika Anda ingin objek ini mewarisi dari yang lain, maka Anda harus menggunakan fungsi konstruktor.
  • Gunakan cara 3 jika Anda ingin menginisialisasi properti objek tergantung pada properti lain atau jika Anda memiliki nama properti dinamis.

Pembaruan: Seperti contoh yang diminta untuk cara ketiga.

Properti tergantung:

Berikut ini tidak bekerja seperti thisyang tidak mengacu pada book. Tidak ada cara untuk menginisialisasi properti dengan nilai-nilai properti lainnya dalam objek literal:

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

sebaliknya, Anda bisa melakukan:

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

Nama properti dinamis:

Jika nama properti disimpan dalam beberapa variabel atau dibuat melalui beberapa ekspresi, maka Anda harus menggunakan notasi braket:

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
sumber
1
terima kasih atas jawaban Anda ... sekarang saya mengerti poin pertama Anda, kami dapat menggunakan way1 jika kami ingin sesuatu seperti ini myFather = orang baru ("John", "Doe", 50, "blue"); myMother = orang baru ("gazy", "Doe", 45, "brown"); myBrother = orang baru ("poll", "Doe", 15, "blue");
Jamna
Saya pikir maksud Anda obj [nama] = 42. Benar?
Keith Pinson
Saya ingin menunjukkan bahwa opsi 2 dan 3 sebenarnya identik, hanya saja Anda menetapkan properti setelah Anda membuat objek. Inilah yang disebut notasi literal , karena Anda menggunakan objek literal untuk membuat objek Anda. Di bawah tenda, ini sebenarnya memanggil "Objek baru ()". Anda dapat membaca lebih lanjut tentang hal ini di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
dudewad
Untuk kasus kedua, apakah masuk akal jika kita menggunakan operator spread ...untuk mewarisi dari objek lain?
6pack anak
114

Ada berbagai cara untuk mendefinisikan suatu fungsi. Ini sepenuhnya didasarkan pada kebutuhan Anda. Berikut adalah beberapa gaya: -

  1. Pembuat objek
  2. Konstruktor literal
  3. Berbasis fungsi
  4. Berbasis Protoype
  5. Berbasis Fungsi dan Prototipe
  6. Berbasis Singleton

Contoh:

  1. Konstruktor objek
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ; 
};
  1. Konstruktor literal
var person = { 
  name : "Anand",
  getName : function (){
   return this.name
  } 
} 
  1. fungsi Konstruktor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  } 
} 
  1. Prototipe
function Person(){};

Person.prototype.name = "Anand";
  1. Kombinasi fungsi / prototipe
function Person(name){
  this.name = name;
} 
Person.prototype.getName = function(){
  return this.name
} 
  1. Singleton
var person = new function(){
  this.name = "Anand"
} 

Anda dapat mencobanya di konsol, jika Anda memiliki kebingungan.

Anand Deep Singh
sumber
HEy @Alex_Nabu - Saya telah membagikan contoh di pos saya. Jika Anda masih menghadapi tantangan, perbarui saya. Saya akan membantu Anda.
Anand Deep Singh
1
tidakkah lebih masuk akal untuk membangun setiap contoh menghasilkan contoh yang sama persis var personpada akhirnya? misalnya dalam konstruktor fungsi yang bisa Anda tambahkan var person = new Person("Anand"). dan ada apa dengan penggunaan semi-colon yang tampaknya acak? : P
cregox
2
Itu akan menambah nilai menjelaskan pro & kontra dari setiap cara.
Ray Tanpa Cinta
10

Tidak ada "cara terbaik" untuk membuat objek. Setiap cara memiliki manfaat tergantung pada kasus penggunaan Anda.

Pola konstruktor (fungsi yang dipasangkan dengan newoperator untuk menjalankannya) menyediakan kemungkinan menggunakan pewarisan prototypal, sedangkan cara lain tidak. Jadi jika Anda ingin warisan prototipal, maka fungsi konstruktor adalah cara yang baik untuk pergi.

Namun, jika Anda menginginkan warisan prototipal, Anda dapat menggunakannya Object.create, yang membuat warisan tersebut menjadi lebih jelas.

Membuat objek literal (contoh:) var obj = {foo: "bar"};berfungsi dengan baik jika Anda memiliki semua properti yang ingin Anda siapkan saat penciptaan.

Untuk menyetel properti nanti, NewObject.property1sintaks umumnya lebih disukai NewObject['property1']jika Anda tahu nama properti. Tetapi yang terakhir berguna ketika Anda tidak benar-benar memiliki nama properti sebelumnya (mis NewObject[someStringVar]. :) .

Semoga ini membantu!

jimbo
sumber
6

Saya kira itu tergantung pada apa yang Anda inginkan. Untuk objek sederhana, saya kira Anda bisa menggunakan metode kedua. Ketika objek Anda tumbuh lebih besar dan Anda berencana menggunakan objek yang serupa, saya kira metode pertama akan lebih baik. Dengan begitu Anda juga dapat memperluasnya menggunakan prototipe.

Contoh:

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

Saya bukan penggemar berat dari metode ketiga, tetapi ini sangat berguna untuk mengedit properti secara dinamis, misalnya var foo='bar'; var bar = someObject[foo];.

Daan Wilmer
sumber
3

Ada banyak cara untuk membuat objek Anda di JavaScript. Menggunakan fungsi konstructer untuk membuat objek atau objek notasi literal menggunakan banyak dalam JavaScript. Juga membuat turunan Obyek dan kemudian menambahkan properti dan metode untuk itu, ada tiga cara umum untuk melakukan membuat objek dalam JavaScript.

Fungsi pembuat

Ada fungsi konstruktor bawaan yang kita semua dapat menggunakannya dari waktu ke waktu, seperti Date (), Number (), Boolean () dll, semua fungsi konstruktor dimulai dengan huruf kapital, sementara itu kita dapat membuat fungsi konstruktor kustom di JavaScript seperti ini:

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

dan Anda dapat memintanya, cukup menggunakan new (), untuk membuat instance konstruktor baru, membuat sesuatu seperti di bawah ini dan memanggil fungsi konstruktor dengan parameter terisi:

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

Objek literal

Menggunakan literal objek adalah kasus pembuatan objek yang sangat sering digunakan dalam JavaScript, ini contoh membuat objek sederhana, Anda dapat menetapkan apa saja ke properti objek Anda selama didefinisikan:

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

Prototyping

Setelah membuat Obyek, Anda dapat membuat prototipe lebih banyak anggota untuk itu, misalnya menambahkan warna ke Kotak kami, kami dapat melakukan ini:

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

Sementara banyak orang di sini mengatakan tidak ada cara terbaik untuk membuat objek, ada alasan mengapa ada begitu banyak cara untuk membuat objek dalam JavaScript, pada 2019, dan ini ada hubungannya dengan kemajuan JavaScript melalui berbagai iterasi yang berbeda. rilis EcmaScript dating kembali ke tahun 1997.

Sebelum ECMAScript 5, hanya ada dua cara untuk membuat objek: fungsi konstruktor atau notasi literal (alternatif yang lebih baik untuk Obyek baru ()). Dengan notasi fungsi konstruktor Anda membuat objek yang dapat dipakai menjadi beberapa instance (dengan kata kunci baru), sedangkan notasi literal memberikan objek tunggal, seperti singleton.

// constructor function
function Person() {};

// literal notation
var Person = {};

Terlepas dari metode yang Anda gunakan, objek JavaScript hanyalah properti pasangan nilai kunci:

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

Dalam versi awal JavaScript, satu-satunya cara nyata untuk meniru warisan berbasis kelas adalah dengan menggunakan fungsi konstruktor. fungsi konstruktor adalah fungsi khusus yang dipanggil dengan kata kunci 'baru'. Dengan konvensi, pengenal fungsi dikapitalisasi, albiet tidak diperlukan. Di dalam konstruktor, kami merujuk pada kata kunci 'ini' untuk menambahkan properti ke objek yang fungsi konstruktor buat secara implisit. Fungsi konstruktor secara implisit mengembalikan objek baru dengan properti yang dihuni kembali ke fungsi panggilan secara implisit, kecuali jika Anda secara eksplisit menggunakan kata kunci pengembalian dan mengembalikan sesuatu yang lain.

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

Ada masalah dengan metode sayName. Biasanya, dalam bahasa pemrograman berbasis Object-Oriented Class, Anda menggunakan kelas sebagai pabrik untuk membuat objek. Setiap objek akan memiliki variabel instance sendiri, tetapi akan memiliki pointer ke metode yang didefinisikan dalam cetak biru kelas. Sayangnya, saat menggunakan fungsi konstruktor JavaScript, setiap kali dipanggil, ia akan mendefinisikan properti sayName baru pada objek yang baru dibuat. Jadi setiap objek akan memiliki properti sayName yang unik. Ini akan menghabiskan lebih banyak sumber daya memori.

Selain meningkatkan sumber daya memori, mendefinisikan metode di dalam fungsi konstruktor menghilangkan kemungkinan pewarisan. Sekali lagi, metode ini akan didefinisikan sebagai properti pada objek yang baru dibuat dan tidak ada objek lain, sehingga pewarisan tidak dapat berfungsi seperti itu. Oleh karena itu, JavaScript menyediakan rantai prototipe sebagai bentuk warisan, menjadikan JavaScript sebagai bahasa prototipe.

Jika Anda memiliki orang tua dan orang tua membagikan banyak properti anak, maka anak tersebut harus mewarisi properti tersebut. Sebelum ES5, hal itu dilakukan sebagai berikut:

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

Cara kami menggunakan rantai prototipe di atas memiliki kekhasan. Karena prototipe adalah tautan langsung, dengan mengubah properti dari satu objek dalam rantai prototipe, Anda juga akan mengubah properti yang sama dari objek lain. Jelas, mengubah metode warisan anak seharusnya tidak mengubah metode orang tua. Object.create menyelesaikan masalah ini dengan menggunakan polyfill. Dengan demikian, dengan Object.create, Anda dapat dengan aman memodifikasi properti anak dalam rantai prototipe tanpa memengaruhi properti yang sama induknya dalam rantai prototipe.

ECMAScript 5 memperkenalkan Object.create untuk menyelesaikan bug yang disebutkan di atas dalam fungsi konstruktor untuk pembuatan objek. Metode Object.create () MENCIPTAKAN objek baru, menggunakan objek yang ada sebagai prototipe objek yang baru dibuat. Karena objek baru dibuat, Anda tidak lagi memiliki masalah di mana memodifikasi properti anak dalam rantai prototipe akan mengubah referensi orang tua ke properti dalam rantai.

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.

Sebelum ES6, berikut adalah pola kreasi umum untuk menggunakan fungsi constructor dan 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);

Sekarang Object.create ditambah dengan fungsi konstruktor telah banyak digunakan untuk pembuatan objek dan pewarisan dalam JavaScript. Namun, ES6 memperkenalkan konsep kelas, yang utamanya adalah sintaksis gula atas warisan berbasis prototipe JavaScript yang ada. Sintaks kelas tidak memperkenalkan model pewarisan berorientasi objek baru ke JavaScript. Dengan demikian, JavaScript tetap merupakan bahasa prototipe.

Kelas ES6 membuat pewarisan jauh lebih mudah. Kami tidak lagi harus menyalin fungsi prototipe kelas induk secara manual dan mengatur ulang konstruktor kelas anak.

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

Secara keseluruhan, 5 strategi berbeda dari Pembuatan Objek dalam JavaScript ini bertepatan dengan evolusi standar EcmaScript.

Donato
sumber
0

Tentu saja ada cara terbaik. Objek dalam javascript memiliki properti enumerable dan nonenumerable.

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

Pada contoh di atas Anda dapat melihat bahwa objek kosong sebenarnya memiliki properti.

Oke, pertama mari kita lihat mana yang merupakan cara terbaik:

var new_object = Object.create(null)

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

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

Pada contoh di atas log akan menampilkan false.

Sekarang mari kita lihat mengapa cara pembuatan objek lainnya tidak benar.

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

Seperti yang dapat Anda lihat di atas, semua contoh masuk dengan benar. Yang berarti jika Anda memiliki kasus bahwa Anda memiliki for inlingkaran untuk melihat apakah objek memiliki properti mungkin akan membawa Anda ke hasil yang salah.

Perhatikan bahwa cara terbaik itu tidak mudah. ​​Anda harus mendefinisikan semua properti objek baris demi baris. Cara lain lebih mudah dan memiliki kode lebih sedikit untuk membuat objek tetapi Anda harus menyadari dalam beberapa kasus. Saya selalu menggunakan "cara lain" dengan cara dan satu solusi untuk peringatan di atas jika Anda tidak menggunakan cara terbaik adalah:

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

Secara umum ada 3 cara untuk membuat Objects-

Yang paling sederhana adalah menggunakan objek literal .

const myObject = {}

Meskipun metode ini adalah yang paling sederhana tetapi memiliki kelemahan yaitu jika objek Anda memiliki perilaku (fungsi di dalamnya), maka di masa depan jika Anda ingin membuat perubahan, Anda harus mengubahnya di semua objek .

Jadi dalam hal ini lebih baik menggunakan Fungsi Pabrik atau Konstruktor. (Siapa pun yang Anda suka)

Fungsi Pabrik adalah fungsi-fungsi yang mengembalikan objek.eg-

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

Fungsi Konstruktor adalah fungsi-fungsi yang menetapkan properti ke objek menggunakan kata kunci "this ".eg-

function constructorFunc(exampleValue){
   this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
shivam bansal
sumber