Struktur dalam Javascript

112

Sebelumnya, ketika saya perlu menyimpan sejumlah variabel terkait, saya akan membuat kelas.

function Item(id, speaker, country) {
    this.id = id;
    this.speaker = spkr;
    this.country = country;
}
var myItems = [
    new Item(1, 'john', 'au'),
    new Item(2, 'mary', 'us')
];

Tapi saya bertanya-tanya apakah ini praktik yang baik. Apakah ada cara lain yang lebih baik untuk mensimulasikan struct di Javascript?

nickf
sumber

Jawaban:

184

Satu-satunya perbedaan antara literal objek dan objek yang dibangun adalah properti yang diwarisi dari prototipe.

var o = {
  'a': 3, 'b': 4,
  'doStuff': function() {
    alert(this.a + this.b);
  }
};
o.doStuff(); // displays: 7

Anda bisa membuat pabrik struct.

function makeStruct(names) {
  var names = names.split(' ');
  var count = names.length;
  function constructor() {
    for (var i = 0; i < count; i++) {
      this[names[i]] = arguments[i];
    }
  }
  return constructor;
}

var Item = makeStruct("id speaker country");
var row = new Item(1, 'john', 'au');
alert(row.speaker); // displays: john
Markus Jarderot
sumber
27
... dan kemudian saya memahami fungsi pabrik. +1 untuk jawaban yang jelas, dapat dimengerti, dan ringkas, bersama dengan contoh pabrik.
Yohanes
Saya suka pendekatan ini, namun hati-hati jika Anda menggunakan kompiler closure. Dalam kasus ini tupel hanya dapat diakses sebagai string, karena propertinya diganti namanya. (Setidaknya dalam mode lanjutan)
kap
Saya ingin tahu tentang efisiensi metode ini dibandingkan literal objek.
c0degeas
Mungkin juga untuk menggunakan kelas JS.
SphynxTech
31

Saya selalu menggunakan literal objek

{id: 1, speaker:"john", country: "au"}
vava
sumber
2
bukankah itu akan membuatnya lebih sulit untuk dipertahankan (jika Anda ingin menambahkan bidang baru di masa mendatang), dan juga lebih banyak kode (mengetik ulang "id", "speaker", "country" setiap saat)?
nickf
5
Ini sama seperti solusi yang dapat dipelihara dengan kelas karena JavaScript tidak peduli dengan jumlah argumen yang Anda panggil fungsi tersebut. Mengetik ulang tidak menjadi masalah jika Anda menggunakan alat yang tepat seperti Emacs. Dan Anda dapat melihat apa yang sama dengan apa yang membuat kesalahan seperti bertukar argumen menjadi usang.
vava
4
Tetapi pro terbesar adalah Anda akan menulis lebih sedikit kode dan itu akan lebih bersih :)
vava
1
Mengetik ulang @vava masih menjadi masalah, karena ada lebih banyak lompatan daripada menyalin arketipe ___ (,,,) yang baru. Juga, tidak ada keterbacaan. Setelah Anda terbiasa dengan pengkodean, new READABLE_PART(ignore everything in here)jadilah sangat mudah dipindai dan mendokumentasikan diri sendiri, bukan {read: "ignore", everything: "ignore", in: "ignore", here: "ignore"} // and then come up with READABLE_PARTdi kepala Anda. Versi pertama dapat dibaca saat muncul dengan cepat. Yang kedua, Anda refactor menjadi struct hanya untuk memahami.
Christopher
19

Masalah sebenarnya adalah bahwa struktur dalam bahasa seharusnya merupakan tipe nilai, bukan tipe referensi. Jawaban yang diajukan menyarankan penggunaan objek (yang merupakan tipe referensi) sebagai pengganti struktur. Meskipun hal ini dapat memenuhi tujuannya, hal ini menghindari titik di mana seorang programmer sebenarnya menginginkan manfaat menggunakan tipe nilai (seperti primitif) sebagai pengganti tipe referensi. Jenis nilai, misalnya, tidak boleh menyebabkan kebocoran memori.

Mario
sumber
8

Saya pikir membuat kelas untuk mensimulasikan struct seperti C, seperti yang telah Anda lakukan, adalah cara terbaik .

Ini cara yang bagus untuk mengelompokkan data terkait dan menyederhanakan parameter yang diteruskan ke fungsi. Saya juga berpendapat bahwa kelas JavaScript lebih seperti struct C ++ daripada kelas C ++, mengingat upaya tambahan yang diperlukan untuk mensimulasikan fitur berorientasi objek nyata.

Saya telah menemukan bahwa mencoba membuat JavaScript lebih seperti bahasa lain menjadi rumit dengan cepat, tetapi saya sepenuhnya mendukung penggunaan kelas JavaScript sebagai struct tanpa fungsi.

peter
sumber
Saya ingin memiliki sesuatu seperti struct, tuple - sesuatu yang memungkinkan koleksi data yang sangat diketik - yang ditangani pada waktu kompilasi dan tidak memiliki overhead dari hashmaps seperti objek
derekdreery
4

Mengikuti jawaban Markus , dalam versi JS yang lebih baru (ES6 menurut saya) Anda dapat membuat pabrik 'struct' lebih sederhana menggunakan Fungsi Panah dan Parameter Istirahat seperti ini:

const Struct = (...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {}))
const Item = Struct('id', 'speaker', 'country')
var myItems = [
    Item(1, 'john', 'au'),
    Item(2, 'mary', 'us')
];

console.log(myItems);
console.log(myItems[0].id);
console.log(myItems[0].speaker);
console.log(myItems[0].country);

Hasil dari menjalankan ini adalah:

[ { id: 1, speaker: 'john', country: 'au' },
  { id: 2, speaker: 'mary', country: 'us' } ]
1
john
au

Anda dapat membuatnya terlihat mirip dengan nametuple Python:

const NamedStruct = (name, ...keys) => ((...v) => keys.reduce((o, k, i) => {o[k] = v[i]; return o} , {_name: name}))
const Item = NamedStruct('Item', 'id', 'speaker', 'country')
var myItems = [
    Item(1, 'john', 'au'),
    Item(2, 'mary', 'us')
];

console.log(myItems);
console.log(myItems[0].id);
console.log(myItems[0].speaker);
console.log(myItems[0].country);

Dan hasilnya:

[ { _name: 'Item', id: 1, speaker: 'john', country: 'au' },
  { _name: 'Item', id: 2, speaker: 'mary', country: 'us' } ]
1
john
au
typoerrpr
sumber
Sepertinya struct dalam C / C ++ dan bahasa lain, tetapi sebenarnya bukan - the, properti pada objek tidak dijamin akan diurutkan seperti berikut: Definisi Objek dari ECMAScript Edisi Ketiga (pdf): 4.3.3 Objek Sebuah objek adalah anggota dari tipe Objek. Ini adalah kumpulan properti tak berurutan yang masing-masing berisi nilai primitif, objek, atau fungsi. Sebuah fungsi yang disimpan dalam properti suatu objek disebut metode
tibetty
3

Saya menggunakan objek gaya JSON untuk struct bodoh (tidak ada fungsi anggota).

Robert Gould
sumber
1

Saya membuat perpustakaan kecil untuk mendefinisikan struct jika Anda bekerja dengan kompatibilitas ES6.

Ini adalah pengurai JKT, Anda dapat melakukan pembayaran repositori proyek di sini JKT Parser

Misalnya, Anda dapat membuat struct Anda seperti ini

const Person = jkt`
    name: String
    age: Number
`

const someVar = Person({ name: "Aditya", age: "26" })

someVar.name // print "Aditya"
someVar.age // print 26 (integer)

someVar.toJSON() // produce json object with defined schema 
Aditya Kresna Permana
sumber
0

Ini lebih banyak pekerjaan untuk disiapkan, tetapi jika pemeliharaan mengalahkan upaya satu kali maka ini mungkin kasus Anda.

/**
 * @class
 */
class Reference {

    /**
     * @constructs Reference
     * @param {Object} p The properties.
     * @param {String} p.class The class name.
     * @param {String} p.field The field name.
     */
    constructor(p={}) {
        this.class = p.class;
        this.field = p.field;
    }
}

Keuntungan:

  • tidak terikat pada urutan argumen
  • mudah diperpanjang
  • ketik dukungan skrip:

masukkan deskripsi gambar di sini

Manuel
sumber