6

I know how to use JS getters and setters for object properties like so

var myObject = {
    value : 0,
    get property() {
        return this.value;
    },
    set property(v) {
        this.value = v;
    }
}

so that calling myObject.property = 2 will set myObject.value, but what I'm wondering is if there is some way to call myObject = 2 and still set myObject.value rather than changing myObject from an object into a number.

It's probably not possible, but javascript is an incredibly flexible language and I thought I'd pose the question to the community before I discarded the idea.

wackozacko
  • 682
  • 1
  • 8
  • 18
  • 1
    Discard this idea. `myObject` is a reference, and reassigning it to something else will... well, reassign it to something else. – Dave Newton Aug 07 '14 at 19:15
  • It doesn't seen to be possible in JavaScript, although internally there's a `DefineOwnProperty` method, specified in the specification, which is only used when creating arguments for functions. The closest thing you can get is to use `DefineProperty` on `window`. – Derek 朕會功夫 Aug 07 '14 at 19:22
  • 3
    I think what you're really after here is overloading the assignment operator, which has been [discussed before](http://stackoverflow.com/questions/3770480/is-there-a-way-to-customize-override-assignment-operations-in-javasscript) – Don Aug 07 '14 at 19:22
  • @DaveNewton you can define getters and setters so when a reference is being assigned, it only executes the setter function and not actually assigning value to that property. – Derek 朕會功夫 Aug 07 '14 at 19:25
  • @Derek朕會功夫 That's pretty different than setting an arbitrary reference to something other than what you're setting it to. Or rather, it's different than making the assignment operator do something other than assign. This is baked into the language. – Dave Newton Aug 07 '14 at 19:28
  • Oops. I downvoted this question thinking that it was an incorrect usage of property descriptors. I didn't know that you can define properties with getters/setters directly. and now my vote is locked. apologies! – Zach Smith Jan 15 '20 at 08:01

2 Answers2

3

It is possible indeed. Only for global variables though.

Object.defineProperties(this, {
    myObject: {
        get: function () {
            return myObjectValue;
        },
        set: function (value) {
            myObjectValue = value;
        },
        enumerable: true,
        configurable: true
    },
    myObjectValue: {
        value: 0,
        enumerable: false,
        configurable: true,
        writable: true
    }
});

myObject = 5;
console.log(myObject);
console.log(delete myObject);

Now, every time you assign a value to myObject, it shall actually run the set function and assign the value to the other property instead. Now, if you wanted to minimize pollution, you could create an IIFE and use variables inside that instead to hold the values, per se.

http://jsbin.com/zopefuvi/1/edit

And here is the version with the IIFE.

http://jsbin.com/puzopawa/1/edit

Siddharth
  • 1,146
  • 3
  • 15
  • 28
  • OP is asking about variables, not properties of the global object. Please explain how this works, and make clear what does get polluted. – Bergi Aug 07 '14 at 23:45
  • @Bergi, variables are indeed properties of the global object, aren't they? And yes, this only works for global variables, naturally. And the second fiddle with the IIFE minimizes pollution to one property on the global object which would be the same as simply creating a global variable. – Siddharth Aug 07 '14 at 23:47
  • 1
    Yes, but *only* global variables are, and you don't want to use them in general, so this solution does not work for arbitrary variables. – Bergi Aug 07 '14 at 23:50
  • True. I agree. Let me add that. Thank you. – Siddharth Aug 07 '14 at 23:51
  • 2
    Unfortunately, the situation I wanted to use it in is not global, but since this answers the question, I'll mark as accepted. – wackozacko Aug 08 '14 at 23:56
0

Just as a side note. I didn't know until reading this question that you could define getters/setters without Object.defineProperty. I was wondering at what the difference was between this 'shorthand' method, and defining getters/setters via Object.defineProperty.

I found, using the myObject example in the question:

var myObject = {
    value : 0,
    get property() {
        return this.value;
    },
    set property(v) {
        this.value = v;
    }
}

that Object.getOwnPropertyDescriptor(myObject, 'property')

returns

get: ƒ property()
set: ƒ property(v)
enumerable: true
configurable: true

So worth mentioning is that property in this case is enumerable, meaning it will show up in loops.

Zach Smith
  • 8,458
  • 13
  • 59
  • 133