3

Is it possible to create a variable that is linked to a function and executes this function every time the variable is being read? A use case would be updated language translations when the call to a certain translation already happened (returning a translation string which might change in future). This is kind of similar to getter methods of a class, but without actually defining a class.

Any idea how this could be done (if at all)?

3
  • Just hide the value inside the function, returning it when called? Commented Nov 27, 2019 at 0:36
  • 2
    Yes, you should be able to hijack 'getter' functionality to do whatever you want, and the "class" syntax is not required, like let myThing = { get myVar() { /*Check sports scores here */} Commented Nov 27, 2019 at 0:39
  • Even though it's possible... I suspect doing this would later result in a debugging nightmare. Reading a getter and having different results each time is understandable, but I would definitely scratch my head if I get a different value every time I read a local variable Commented Nov 27, 2019 at 0:49

2 Answers 2

6

You can use Object.defineProperty() to do this

Object.defineProperty(this, 'prop', { // adding to whatever "this" context is
  get: () => Math.random()
})

console.info('prop get #1', prop)
console.info('prop get #2', prop)

Sign up to request clarification or add additional context in comments.

4 Comments

Seems to work fine. Any caveats other than that it's nonintuitive?
What you're asking for is non-intuitive anyway ;)
I know - that's not a caveat for me and wasn't meant as criticism ;-).
One thing I noticed is that I can't pass the reference to this variable disguised as a function to another variable without triggering evaluation (i.e. a call of get()), but it's hard to differentiate those two cases as they are both using = as in otherProp = prop.
1

One option is to take advantage of the fact the global object can have properties defined on it that are implicitly in-scope. In a web-browser the Window object is the global object, so this:

<script>
var foo = 123;

function bar() { console.log( foo ) };
bar();
</script>

Is the same as this:

<script>
document.window.foo = 123;

function bar() { console.log( foo ) };
bar();
</script>

Is (more-or-less) the same as this:

<script>
Object.defineProperty( window, "foo", { value: 123 } );

function bar() { console.log( foo ) };
bar();
</script>

So we can abuse Object.defineProperty to get the effect you want, with the caveat that it won't work inside JavaScript scopes where global's properties are not accessible.

<script>
function createMagicVariable( name, func ) {

    var propDef = {
        get: func
    };
    Object.defineProperty( window, name, propDef );
}
</script>

Used like so:

<script>

function getRandom() { return Math.random(); }

createMagicVariable( 'foo', getRandom );

console.log( foo );
console.log( foo );
console.log( foo );

</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.