0

I'm using straight Javascript (no JQuery or anything like that, please). I've implemented a class which wraps an array, thus:

class Ctrls
{
    _items = new Array();
        
    constructor()
    {
        this._items = new Array();
    }   
    
    Add(oCtrl)
    {
        this._items.push( { key:oCtrl.Name, value:oCtrl } );
    }   
    
    Clear()
    {
        this._items = new Array();
    }   
    
    get Count()
    {
        return this._items.length;
    }   
    
    get Item(index)
    {
        // get the index'th item. 
        // If item is numeric, this is an index.
        // If item is a string, this is a control name
        if (Number.isInteger(index))
        {
            return this._items(index).value;
        }
        else
        {
            item = this._items.find(element => (element.value.Name == index));
            return item;
        }
    }   
    
    get Items()
    {
        return this._items; // in case we desperately need to
    }
}

I get an error on page load, at get Item(index), which is Uncaught SyntaxError: Getter must not have any formal parameters. I come from C# world and am looking for an equivalent of:

public Ctrl Item(iIndex)
{
    get
    {
        return _items[iIndex];
    }
}

How do I index a getter in Javascript?


Edit(1): I've had suggestions to turn get Item into a function, but if I change the definition to this:

    function GetItem(index) // returns Ctrl
    {
        // get the index'th item. 
        // If item is numeric, this is an index.
        // If item is a string, this is a control name
        if (Number.isInteger(index))
        {
            return this._items(index).value;
        }
        else
        {
            item = this._items.find(element => (element.value.Name == index));
            return item;
        }
    }   

I get this error on pageload: Uncaught SyntaxError: Unexpected identifier at the line function GetItem...


Edit(2): Modified the above to read:

    GetItem(index) // returns Ctrl
    {
        // get the index'th item. 
        // If item is numeric, this is an index.
        // If item is a string, this is a control name
        if (Number.isInteger(index))
        {
            return this._items(index).value;
        }
        else
        {
            item = this._items.find(element => (element.value.Name == index));
            return item;
        }
    }   

as functions within classes do not use the function keyword, oddly. This now works. Thank all.

Mark Roworth
  • 409
  • 2
  • 15
  • How do you imagine the invocation of the getter looks like from the outside? That is, what code would you want to result in the getter being called? You can't pass a parameter to a getter - you need another technique, like a plain function. – CertainPerformance Mar 07 '22 at 17:29
  • Not 100% what the purpose of this function is. As @CertainPerformance said, how are you planning on using this? JS already has an `indexOf()` function for arrays. – Jeff B Mar 07 '22 at 17:31
  • You can use a [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) getter [as shown here](https://stackoverflow.com/a/25658975/1563833) – Wyck Mar 07 '22 at 17:31
  • 4
    My best suggestion: don't try to C# your JS. The code you're writing makes my skin crawl and triggers my trauma from my days in .NET world. The way you write code in JS is different than what you're used to in C#. Even the whole idea of classes in JS is not even "real" - it's just syntactic sugar over prototypal constructs. – Ryan Wheale Mar 07 '22 at 17:39
  • `this._items(index)` should be `this._items[index]` – chiliNUT Mar 07 '22 at 17:46
  • Hi @Ryan, I think this is fundimentally my problem. Yes, I'm strongly from a C# background. Trying to get my head around doing things differently, but struggling, especially with the asynchronous side of thing (a different issue). What would you suggest? I need additional methods on Ctrls to derive aggregate information and apply actions to all the elements in _items. What sort of approach should I take? – Mark Roworth Mar 07 '22 at 17:46
  • 2
    That being said, you can't pass parameters to getters in JS. You should just create a method: `getItem(index) { ... }` and call it via `instance.getItem(3)`. I recommend getting comfortable with the language... which is just a task that takes time. It takes a while to shake .NET ways of thinking... not really sure the best advice here. – Ryan Wheale Mar 07 '22 at 17:46
  • @CertainPerformance, approx it would look like this: ```c = new Ctrls(); c.Add(new Ctrl... ); a = c.Item(0); ``` – Mark Roworth Mar 07 '22 at 17:48
  • 2
    @MarkRoworth The Item getter is the (first) syntactical problem - how do you want that to look? Essentially you can either do `console.log(c.Item)` and pass no parameters, or don't use a getter at all `console.log(c.getItem(1))` and pass a parameter – CertainPerformance Mar 07 '22 at 17:50
  • @CertainPerformance - yup, am looking to use a function. Thank you. – Mark Roworth Mar 07 '22 at 17:51

1 Answers1

1

"you can't pass parameters to getters in JS". Theoretically: yes, you cannot do that. But practically: functions are first-class citizens in JS, so they can be arguments or return values of a function. You can do it like this:

class GetterWithParameter {
  constructor() {
    this.array = ["index 0", "index 1", "index 2"]
  }
  get itemAtIndex() {
    return (idx) => this.array[idx]
  }
}

const getterWithParameter = new GetterWithParameter()

const idx0 = getterWithParameter.itemAtIndex(0)
const idx1 = getterWithParameter.itemAtIndex(1)
const idx2 = getterWithParameter.itemAtIndex(2)

console.log("item at index 0:", idx0)
console.log("item at index 1:", idx1)
console.log("item at index 2:", idx2)

So, while the getter cannot have arguments, you can return a function that can receive an argument - and use that.

Of course, the usage seems identical to defining a function on the class that requires the same argument - but still, you are using a getter.

muka.gergely
  • 8,063
  • 2
  • 17
  • 34
  • Thanks @muka.gergely. This makes sense. Much appreciated. I ended up using a function, but I may use this in the future. – Mark Roworth Mar 07 '22 at 18:30