Is it possible to implement dynamic getters/setters in JavaScript?

Asked
Active3 hr before
Viewed126 times

7 Answers

possibledynamicimplement
90%

You could, of course, implement a function to do it, but I'm guessing you probably don't want to use f = obj.prop("foo"); rather than f = obj.foo; and obj.prop("foo", value); rather than obj.foo = value; (which would be necessary for the function to handle unknown properties).,No, JavaScript doesn't have a catch-all property feature. The accessor syntax you're using is covered in Section 11.1.5 of the spec, and doesn't offer any wildcard or something like that.,The gist is that you can define a getter and/or setter on an object like so:,But again, I can't imagine you'd really want to do that, because of how it changes how you use the object.

"use strict";
if (typeof Proxy == "undefined") {
   throw new Error("This browser doesn't support Proxy");
}
let original = {
   "foo": "bar"
};
let proxy = new Proxy(original, {
   get(target, name, receiver) {
      let rv = Reflect.get(target, name, receiver);
      if (typeof rv === "string") {
         rv = rv.toUpperCase();
      }
      return rv;
   }
});
console.log(`original.foo = ${original.foo}`); // "original.foo = bar"
console.log(`proxy.foo = ${proxy.foo}`); // "proxy.foo = BAR"
load more v
88%

JavaScript comes with the Proxy constructor to let us create an object that is a facade on another object.,For instance, we can add a dynamic getter to it by writing:,For instance, we can write:,Then we use the Proxy constructor to create a proxy with the original object.

For instance, we can add a dynamic getter to it by writing:

const original = {
   "foo": "bar"
};
const proxy = new Proxy(original, {
   get(target, name, receiver) {
      let rv = Reflect.get(target, name, receiver);
      if (typeof rv === "string") {
         rv = rv.toUpperCase();
      }
      return rv;
   }
});
console.log(original.foo)
console.log(proxy.foo);
load more v
72%

I am trying to solve a problem that came to my mind lately. Let's say we would want and would know how to make a point in having dynamic getters and setters in javascript, more like those in php (__get, __set). But as javascript does not have a catch-all property the only thing we could do is to provide a list of possible keys and iterate to add getters and setters on those only, and hope none other will ever come.,What you're trying to accomplish (a global getter for any undefined property) is outside the scope of cross-browser JavaScript.,what if I would use the original window.undefined getter and setter, after all it must be called every time I screw up and misspell a word or something.,This may be useful if you can predict the name of possibly undefined properties ahead of time. Even so it's quite hacky and bad form to add an accessor to all objects for a property that might be undefined.

But the problem is not by far solved. So the next approach that came to my mind was to use a nasty hack with try and catch, so anytime a name would be undefined in an object to use the catch as a getter (at least) and then resume the code, hard and maybe pointless thing to do. But from here came my second problem, in an use such as this :

console.log(g.someundefinedproperty);

So I tried

Object.defineProperty(window, 'undefined', {
   get: function() {
      // functional code, including getting the caller and figuring out
      // where we are, and what we have to do... easy :D

      console.log('works');
   },
   set: function() {
      // some couple more fine hacks here
      console.log('this too');
   }
});
load more v
65%

I am aware of how to create getters and setters for properties whose names one already knows, by doing something like this:,Now, my question is, is it possible to define sort of catch-all getters and setters like these? I.e., create getters and setters for any property name which isn't already defined.,I started this post with the sole purpose of learning why that things happened, and I finally did. So in case there's someone else interested in the "whys" here they are:,While the anonymous function gets executed right away, the getters/setters get executed for the first time when they are called. In that moment, the value of i will always be the last because it has already iterated for all the properties... and will always return properties[i] which is the last value, in this case the age.

I am aware of how to create getters and setters for properties whose names one already knows, by doing something like this:

// A trivial example:
function MyObject(val) {
   this.count = 0;
   this.value = val;
}
MyObject.prototype = {
   get value() {
      return this.count < 2 ? "Go away" : this._value;
   },
   set value(val) {
      this._value = val + (++this.count);
   }
};
var a = new MyObject('foo');

alert(a.value); // --> "Go away"
a.value = 'bar';
alert(a.value); // --> "bar2"
load more v
75%

Sometimes it is desirable to allow access to a property that returns a dynamically computed value, or you may want to reflect the status of an internal variable without requiring the use of explicit method calls. In JavaScript, this can be accomplished with the use of a getter. , In the following example, the object has a getter as its own property. On getting the property, the property is removed from the object and re-added, but implicitly as a data property this time. Finally, the value gets returned. , Starting with ECMAScript 2015, you can also use expressions for a computed property name to bind to the given function. , An additional optimization technique to lazify or delay the calculation of a property value and cache it for later access are smart (or "memoized") getters. The value is calculated the first time the getter is called, and is then cached so subsequent accesses return the cached value without recalculating it. This is useful in the following situations:

{
   get prop() {
      ...
   }
} {
   get[expression]() {
      ...
   }
}
load more v
40%

with the default method syntax (getter and setter methods),,You can create getters and setters in three different ways:,Besides getters, you can also create setters using JavaScript’s default method syntax. Below, you can see how the setColor() and setMake() methods compare to the previously declared getters.,With getters and setters, you can only get and set the values of properties but not methods, as methods are not static.

var myCar = {
   color: "blue",
   make: "Toyota"
};
load more v
22%

As objects in JavaScript are dynamic, you can also define getters-setters after creating the object.,Let us add a new property brand and a getter for it after creating a car.,As we know from This Tutorial that Objects in JavaScript are dynamic, we can either define properties while declaring the Constructor Function,Getters and Setters in JavaScript | JavaScript & Object Oriented Programming | Part 10

This is how we can use Object.defineProperty() inside a Constructor Function

function Car(make, model) {
   this.make = make;
   this.model = model;

   var maxSpeed = 200;

   Object.defineProperty(this, 'topSpeed', {
      get: function() {
         return maxSpeed;
      }
   });
}

var car = new Car('Toyota', 'Corolla');
load more v

Other "possible-dynamic" queries related to "Is it possible to implement dynamic getters/setters in JavaScript?"