Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript variable that behaves like a function

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)?

like image 562
orange Avatar asked Aug 06 '26 08:08

orange


2 Answers

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)
like image 152
Phil Avatar answered Aug 07 '26 22:08

Phil


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>
like image 23
Dai Avatar answered Aug 07 '26 21:08

Dai