Magnogen
Magnogen

Reputation: 15

Where does a local variable get stored, and how can I define a getter/setter for one?

So in JavaScript, I know that when you define a variable in the global scope, like this,

let a = 0;
console.log(a); // > 0

it's (more or less) the same as defining a property on the window object:

window.a = 0;
console.log(a); // > 0, exactly the same

Is there a way to do this "window method" within the local scope a function?


The reason I ask is because you can define a getter/setter on a window quite easily (which I find very helpful, especially when I want to make personal libraries and such), and be able to use the variables it defines just like a regular variable:

let value = 0;
Reflect.defineProperty(window, 'counter', {
  get() { return value++ },
  set(v) { value = v }
});
console.log(counter); // > 0
console.log(counter); // > 1
console.log(counter); // > 2
counter = 100;
console.log(counter); // > 100
console.log(counter); // > 101
// etc

... but as soon as you put it into a function, it works, but the variable becomes defined on the window object, making it leak out of the scope of the function.

Where do variables declared inside the local scope of a function get stored? How can I define one of them with a getter/setter?


I've Tried

In this example, the variable a doesn't leak out as it isn't defined on the window object.

(function () {
  let a = 42;
  console.log(a); // > 42
  console.log(window.a); // > undefined
  console.log(this.a); // > undefined, this === window in this case
})();

... but it's not defined on this either, as this is the same as window. So then I tried binding it to a custom object:

(function () {
  let a = 42;
  console.log(window.a); // > undefined, not here...
  console.log(this.a); // > undefined,
                       // even though `this` isnt the window anymore,
                       // and it is an object that can be changed.
  console.log(this.b); // > 69, see?
}).bind({ b: 69 })();

(note: using new (function () { ... })() does the same as this bind example)


tl;dr

(function () {
  let value = 0;
  Reflect.defineProperty(this, 'counter', {
    get() { return value++ },
    set(v) { value = v }
  });
  counter; counter; // increment twice
  console.log(counter); // > 2
  counter = 100;
  counter; counter; counter; // increment thrice
  console.log(counter); // > 103
  // etc
})();
console.log(counter); // > 104
// ^ this should throw an error saying that counter
// isn't defined, but it is - on the window. I only
// want it defined within the function scope.
  1. Is there a way to define a variable only within the local scope a function?
  2. Where do variables declared inside this local scope get stored? How can I define one of them with a getter/setter?

Upvotes: -3

Views: 120

Answers (1)

Magnogen
Magnogen

Reputation: 15

I've figured it out, no thanks to the StackOverflow community.

For anyone interested, I'd recommend using with. (shocking, I know.)

// make a useful function
const install = (canvas) => ({
  get width()  { return 0|canvas.width },
  set width(v) { canvas.width = 0|v },
  get height()  { return 0|canvas.height },
  set height(v) { canvas.height = 0|v },
  ctx: canvas.getContext('2d')
});
// use it in scope
with (install(document.getElementById('my_canvas'))) {
  width = height = 256;
  ctx.fillStyle = 'black';
  ctx.fillRect(0, 0, width, height);
}
console.log(width); // error: width is not defined

with docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with

Upvotes: -1

Related Questions