1

Is there a way in Javascript to temporarily replace a variable defined in an outer scope, but only keep that value during the inner scope, as there is in other languages like C++? For example:

const debug = require('debug')('mymodule');

function example() {
    // Temporarily replace main `debug` variable with value that
    // only persists for this function
    const debug = debug.extend('myfunction');

    debug('should be in mymodule.myfunction');
}

debug('should be in mymodule');

When I try to do this, Node complains that I'm accesing the inner debug before I have defined it, when what I really want to do is access debug from the parent scope.

Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • You can override the higher scoped variable with a locally declared one, but then you can't access the higher scoped one. – jfriend00 Jan 19 '20 at 04:17
  • @jfriend00: Technically I don't need to access the higher scoped one after the local one has been defined, since I would like the local one to replace it for the duration of the function. – Malvineous Jan 19 '20 at 04:21
  • But, you can't do `const debug = debug.extend('myfunction');` because the new `const debug` is defined (but not initialized) in this block scope already so you can no longer access the higher scoped one where you are trying to. All `const` variables are "hoisted" to the top of their scope so it is already overriding/hiding the higher scoped one at the very beginning of the block it is declared in. – jfriend00 Jan 19 '20 at 04:24
  • Yes exactly, so I am hoping someone has come up with a clever solution to work around that issue :-) – Malvineous Jan 19 '20 at 04:40
  • Well, you can save the higher scoped variable to a differently named variable, then introduce a new block scope where you define the local override. Then, you can access both the higher scoped copy and the newly defined one. See my answer. – jfriend00 Jan 19 '20 at 04:55

2 Answers2

1

You can override the higher scoped one with a local definition. But when doing that, you can no longer access the higher scoped one.

When you do this:

const debug = debug.extend('myfunction');

You can't access debug.extend() because the local debug has already been defined, but not yet initialized.

The simplest solution is to just use a different named local variable. But, if you you don't want to do that and you want to retain access to the higher scoped one, you have to save a copy of it to another variable in a higher level block scope than where you define the new one so you can then access both.

const debug = require('debug')('mymodule');

function example() {
    // in a scope higher than where we define new debug variable,
    // save a copy of it so we can still access it
    const oldDebug = debug;

    // create another block scope to contain the new debug definition
    // and not interfere with saving the previous one above
    {
        const debug = oldDebug.extend('myfunction');

        debug('should be in mymodule.myfunction');
     }
}

debug('should be in mymodule');

Another classic way to handle this is to pass the debug argument into your function and named the parameter something different. Then you can use both the new and the old values.

const debug = require('debug')('mymodule');

function example(oldDebug) {
    const debug = oldDebug.extend('myfunction');
    debug('should be in mymodule.myfunction');
}
example(debug);

debug('should be in mymodule');
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • This is similar to what I ended up doing, although I added `const g_debug = debug` at the top level and just used `const debug = g_debug.extend()` in the function itself. It's still a bit messy though so I am hoping for something nicer! – Malvineous Jan 19 '20 at 06:25
  • Added another option with passing the higher scoped variable into your function and giving the parameter a different name. This is cleaner than creating the new block scope. – jfriend00 Jan 19 '20 at 19:51
0

There might be better solutions, but I got it to work like that:

debug = 'foo';

function example() {
  const debug = this.debug + 'bar';
  console.log(debug); // prints 'foobar'
}

example();
console.log(debug); // prints 'foo'

or, if you want to keep the const keyword:

const debug = 'foo';

function example(debugRef) {
  const debug = debugRef + 'bar';
  console.log(debug); // prints 'foobar'
}

example(debug);
console.log(debug); // prints 'foo'
Stratubas
  • 2,939
  • 1
  • 13
  • 18
  • 1
    I'm really hoping to do it without having to add an extra parameter to all my functions though, as there are many of them and it will make the code very cluttered! – Malvineous Jan 19 '20 at 04:22
  • @Malvineous yupp! So do I. Marked as favorite, hope we'll get a better answer, since I've been there, and forced myself to pick a different name for the variable.. – Stratubas Jan 19 '20 at 04:25