Search code examples
javascriptsyntaxecmascript-2016

Is there a way to reuse the if(...) condition's value in the underlying scope?


Why

I'm a sucker for compact code and new language features. Therefore, I'm trying to find a way to reuse the value of the condition statement which opened the current scope without saving this beforehand as a variable in the parent scope, where it has no further use.

This would make my code more compact, yet easier to read, which is a pretty subjective feat. There probably are multiple of approaches to this, so all kinds of solutions are welcome (preferrably ES8, this is not for production use/professional environments).

Clarification:

The following function is cpu-intensive

fetchData()      // returns [object Object] or false on error

It can also be an input stream whose output will differ upon every function call, or a key-value pair lookup which has to happen thousands of times in a short period but can only happen synchronously/blocking.

My current approach:

I have to type data 3 times and it pollutes the global scope. Also, while debugging with breakpoints, the variable is not found in the smallest possible scope.

let data = fetchData()

if (data)
  useData(data)
else
  error()

Not a good solution:

The data variable still occurs 3 times, pollutes the parent scope and you don't know what it means yet upon declaration. Single equation (=) sign can be interpreted wrongly by the reader OR corrected by someone else by mistake.

let data
if (data = fetchData())
  useData(data)

The lazy way:

if (fetchData())
  use(fetchData())

What i wish for:

The 'let' avoids interpreting it as an == conditional statement:

if (let data = fetchData()) { // data is declared in the child scope
  parseData(data)
} else {
  console.error('meh')
}

Result: SyntaxError: Unexpected identifier

or

if (fetchData()) {
  parseData(fi)
}

or

// some kind of symbol, i know this is xor, but it seemed appropriate
if (long.object.key.value().chain.data)
  return JSON.parse(^)

or

if (fetchData()) {
  parseData(condition.value)   // or .pop() or just 'condition'
}

I just feel like it's an information overload when looking back at my current approach, even if it has its advantages. I believe this can improve readability in situations where code is really dense or where function/variable names are so obvious they almost form a sentence.


Solution

  • No, there is no such syntax feature. The way to go is either a block scope

    {
      const data = fetchData()
      if (data)
        useData(data)
      else
        error()
    }
    

    or an IIFE

    (function(data) {
      if (data)
        useData(data)
      else
        error()
    }(fetchData()));
    

    which you can of course also make into a reusable function:

    function If(predicate, then, other) {
        return function(value) {
            if (predicate) then(value) else other(value)
        };
    }
    If(Boolean, useData, error)(fetchData());