[javascript] Structs in Javascript

Previously, when I needed to store a number of related variables, I'd create a class.

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')
];

But I'm wondering if this is a good practice. Are there any other, better ways to simulate a struct in Javascript?

This question is related to javascript struct

The answer is


I made a small library to define struct if you work with ES6 compatibility.

It is a JKT parser you may checkout the project repository here JKT Parser

For an example you may create your struct like this

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 

The real problem is that structures in a language are supposed to be value types not reference types. The proposed answers suggest using objects (which are reference types) in place of structures. While this can serve its purpose, it sidesteps the point that a programmer would actual want the benefits of using value types (like a primitive) in lieu of reference type. Value types, for one, shouldn't cause memory leaks.


I use objects JSON style for dumb structs (no member functions).


I always use object literals

{id: 1, speaker:"john", country: "au"}

I think creating a class to simulate C-like structs, like you've been doing, is the best way.

It's a great way to group related data and simplifies passing parameters to functions. I'd also argue that a JavaScript class is more like a C++ struct than a C++ class, considering the added effort needed to simulate real object oriented features.

I've found that trying to make JavaScript more like another language gets complicated fast, but I fully support using JavaScript classes as functionless structs.


Following Markus's answer, in newer versions of JS (ES6 I think) you can create a 'struct' factory more simply using Arrow Functions and Rest Parameter like so:

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

The result of running this is:

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

You can make it look similar to Python's namedtuple:

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

And the results:

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

I use objects JSON style for dumb structs (no member functions).


I always use object literals

{id: 1, speaker:"john", country: "au"}

I think creating a class to simulate C-like structs, like you've been doing, is the best way.

It's a great way to group related data and simplifies passing parameters to functions. I'd also argue that a JavaScript class is more like a C++ struct than a C++ class, considering the added effort needed to simulate real object oriented features.

I've found that trying to make JavaScript more like another language gets complicated fast, but I fully support using JavaScript classes as functionless structs.


I use objects JSON style for dumb structs (no member functions).


Following Markus's answer, in newer versions of JS (ES6 I think) you can create a 'struct' factory more simply using Arrow Functions and Rest Parameter like so:

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

The result of running this is:

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

You can make it look similar to Python's namedtuple:

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

And the results:

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

I use objects JSON style for dumb structs (no member functions).


I always use object literals

{id: 1, speaker:"john", country: "au"}

I always use object literals

{id: 1, speaker:"john", country: "au"}

It's more work to set up, but if maintainability beats one-time effort then this may be your case.

/**
 * @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;
    }
}

Advantages:

  • not bound to argument order
  • easily extendable
  • type script support:

enter image description here


The real problem is that structures in a language are supposed to be value types not reference types. The proposed answers suggest using objects (which are reference types) in place of structures. While this can serve its purpose, it sidesteps the point that a programmer would actual want the benefits of using value types (like a primitive) in lieu of reference type. Value types, for one, shouldn't cause memory leaks.


It's more work to set up, but if maintainability beats one-time effort then this may be your case.

/**
 * @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;
    }
}

Advantages:

  • not bound to argument order
  • easily extendable
  • type script support:

enter image description here


I made a small library to define struct if you work with ES6 compatibility.

It is a JKT parser you may checkout the project repository here JKT Parser

For an example you may create your struct like this

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