nowox
nowox

Reputation: 29096

Restricting the scope of an assignment in conditional in JavaScript

The following code pushes all the points below the limit into data, until getPoint returns null.

while ((x = getPoint()) && x < limit) {
   data.push(x)
}

console.log(x, 'x should be undefined here')

In this particular case I use an assignment in a conditional, I know it looks ugly, but the question focuses on x which is not local to the block. I tried to place a let there, but it doesn't work.

Is it possible to restrict the scope of x inside the while statement?

Another working implementation would be this one, but in this case I double the test on x:

do {
  let x = getPoint() 
  if (x && x < limit) {
    data.push(x)
  } 
} while(x && x < limit) 

or

while (true) {
  let x = getPoint()
  if (!x || x >= limit) {
    break;
  }
  data.push(x)
}

or

function* getPointIterator(limit) {
  let x = getPoint()
  while(x && x < limit) {
    yield x;
  }
}

data.push(...getPointIterator(limit))

Upvotes: 2

Views: 80

Answers (2)

Dennis Vash
Dennis Vash

Reputation: 53894

1. Code block {...}

You can use a “bare” code block {…} to isolate variables into a “local scope”.

{
  // do some job with local variables that should not be seen outside

  let message = "Hello";

  alert(message); // Hello
}

alert(message); // Error: message is not defined

For your case:

const limit = 3;
let y = 0;
const getPoint = () => y++;

{
    let x = 0;
    while ((x = getPoint()) && x < limit) {
        console.log(x);
    }
}
console.log(x, 'x should be undefined here');

The code outside of the block (or inside another script) doesn’t see variables inside the block, because the block has its own Lexical Environment.

2. IIFE (function {...})

You can use so-called “immediately-invoked function expressions” (abbreviated as IIFE) used for this purpose.

They look like this:

 (function() {

  let message = "Hello";

  alert(message); // Hello

})();

For your case:

const limit = 3;
let y = 0;
const getPoint = () => y++;

(function () {
    let x = 0;
    while ((x = getPoint()) && x < limit) {
        console.log(x);
    }
})();
console.log(x, 'x should be undefined here');

Here a Function Expression is created and immediately called. So the code executes right away and has its own private variables.

The Function Expression is wrapped with brackets (function {...}), because when JavaScript meets "function" in the main code flow, it understands it as the start of a Function Declaration.

Upvotes: 1

gaetanoM
gaetanoM

Reputation: 42054

You may consider to change the while loop with a for loop:

var limit = 3;
var r = 2;
var data = [];

function getPoint() {
    return r++;
}


for (let x=0; (x = getPoint()) && x < limit;) {
    data.push(x)
}

console.log(typeof(x) === 'undefined' ? 'undefined' : x, 'x should be undefined here')

Upvotes: 2

Related Questions