0

Edit This is not a duplicate b/c I can't use a setter b/c of its limitaions, and these are not "dynamic" properties that don't get defined until runtime. I was looking for the same thing that vb.net supports...property setters with arguments. In such a case you get the extra arguments coming into the setter of the property, but the property is defined at runtime (yes I guess it's a meta property). I knew that won't work so was looking for an emulation of that.

I can use any solution up through ES6 if that helps, but I don't have to. This isn't necesarily an ES6 question.

Is there any way in the language to emulate the calling convention I seek?

var myClass = new MyClass();
myClass.Setting('mysettingname') = 4;

I know I can do something like myClass.Setting['mysettingname'] = 4;, but I need code to run when it's set. That's the wrinkle.

ES5.1 JavaScript Setters are not a solution. If you add an argument to the setter it won't run:

MyClass = function(){

  set setting(name, value) { // error b/c of name
    // code that needs to run
  }
};

In php they have magic getters and setters, like this:

   public function __set($key, $value) {
      // assign value for key UserID to _userID property
   }

   public function __get($key) {
      // return value of _userID for UserID property
   }

And in vb.net they have properties with parameters:

Public Property Marks(Byval index as Integer) as Integer
Get
    If (index < NoofSubjects()) And index >= 0 Then
           return _marks(index)
    Else
    Throw new Exception("Index should be in the range 0 to " & (NoofSubjects-1))
    End If
End Get 

Set(Byval value as Integer)
    If (index < NoofSubjects()) And index >= 0 Then
    _marks(index) = value
    Else
    Throw new Exception("Index should be in the range 0 to " & (NoofSubjects-1))
    End If

End Set
End Property
toddmo
  • 20,682
  • 14
  • 97
  • 107
  • Maybe try to explain what you're trying to do, so someone can present an alternative. – Steven Moseley Sep 14 '16 at 17:11
  • Front an object with a method for setting values to it, do whatever you want. – Dave Newton Sep 14 '16 at 17:11
  • @Gothdo, I know what getters and setters are. setters have a limitation. So I can't use a setter. So knowing all about setters won't help me do what I'm tying to do here. – toddmo Sep 14 '16 at 17:12
  • 1
    what's wrong with something like `myClass.Setting('mysettingname', 4);` ? – rydrman Sep 14 '16 at 17:13
  • @rydrman, that's what I'm currently doing. But I think `myClass.Setting('mysettingname') = 4;` looks more elegant, so I'm seeing if the language supports it. – toddmo Sep 14 '16 at 17:15
  • Why not just `myClass.mysettingname = 4;`? – Steven Moseley Sep 14 '16 at 17:16
  • @StevenMoseley, I need code to run when it's set. And I can't hard code the `mysettingname` part. – toddmo Sep 14 '16 at 17:17
  • Not in the way you write, but what exactly is the code you want to run? You could have a getter return a settings object with a `mysettingname` property you assign to. Or you could use a proxy in a similar way on assignment. – Alexander O'Mara Sep 14 '16 at 17:19
  • 1
    what you are really looking for is dynamic getter/setter where the property name is not known until runtime: http://stackoverflow.com/questions/7891937/is-it-possible-to-implement-dynamic-getters-setters-in-javascript – rydrman Sep 14 '16 at 17:20
  • Change your title to "Magic setter / getter for JS", so it explains what you're trying to do – Steven Moseley Sep 14 '16 at 17:21
  • @StevenMoseley, I'm sorry but since magic has many meanings I don't think that explains it better than the current title. Are you being sarcastic? – toddmo Sep 14 '16 at 17:27
  • @toddmo Not joking. The behavior you're trying to create is equivalent to PHP's "magic" `__set` and `__get` methods - see here: http://php.net/manual/en/language.oop5.magic.php - I'm not familiar with any other language that does this innately, or any other use of the terms "magic setter" and "magic getter", much less "magic" alone as it pertains to programming. – Steven Moseley Sep 14 '16 at 18:48
  • @StevenMoseley, in vb.net they are just a feature of property setters. Funny but c# in .net does not allow this. php folks would understand but I guess no one else would. But I could reference it in my question I suppose. – toddmo Sep 14 '16 at 20:44

1 Answers1

2

You can use a Proxy:

class MyClass {}

const myClass = new Proxy(new MyClass, {set: (target, property, value) => {
  // Do here whatever you want with property and value
  console.log(`property: ${property}, value: ${value}`)
  return target[property] = value
}})

myClass.mysettingname = 4
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • Would you say going outside the original class definition itself (as is done with a proxy), is the only way to get a calling convention that has the appearance of `myClass.Setting('mysettingname') = 4;` or `myClass.mysettingname = 4;` (with the "property name" on the left hand side of the assignment operator)? – toddmo Sep 14 '16 at 17:31
  • @toddmo If you don't want to go outside the class definition, you can return the Proxy in the class constructor. – Michał Perłakowski Sep 14 '16 at 17:33