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?
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)
(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.
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