2

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))
5
  • 2
    You can try use {} block for restricting lexical scope Commented Aug 16, 2018 at 20:52
  • 1
    alternatively, use a for loop: for (let x; (x = getPoint()) && x < limit;) {} Commented Aug 16, 2018 at 20:55
  • @Hamms, you're right it is better with a for loop Commented Aug 16, 2018 at 20:57
  • @DennisVash How would you restrict the lexical scope of a global variable with {}? Commented Aug 16, 2018 at 20:57
  • related: stackoverflow.com/questions/42348427/… Commented Jan 13, 2024 at 2:14

2 Answers 2

2

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

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

Comments

1

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.

2 Comments

@DennisVash Why don't you change your answer to show that?
@Barmar added both cases

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.