1

I want to do something like this:

function defineGlobalConst(){
     const s = 10;
}

but I would like to access variable s from anywhere in my code, as I didn't type "const"

3 Answers3

9

You can define a global variable like this:

In a browser:

function defineGlobalConst(){
     window.s = 10;
}

In node:

function defineGlobalConst(){
     global.s = 10;
}

If you want it to be a constant you could use defineProperty and a getter:

Object.defineProperty(window, "s", { 
  get: () => 10,
  set: () => { throw TypeError('Assignment to constant variable.') },
});
griin
  • 29
  • 5
Anthony Garcia-Labiad
  • 3,531
  • 1
  • 26
  • 30
  • I'm working on browser and I want it to be constant, so as I understand: I shouldn't use windows.s = 10 because it wont be constant, and I should use defineProperty? and what does set: () ... mean? get: ().. gives value to s as I see – Abdallah Barghouti Oct 05 '20 at 21:42
  • 3
    It is creating a property in the window object, with a getter and setter. The getter is returning the value but the setter is throwing an error. As a result, if you try to change the value of s by running `s = 20`, it won't work and instead throw an error. – Anthony Garcia-Labiad Oct 05 '20 at 21:49
  • What if you need a non-primitive to be the value? For this exact example it works, but if you need an Object or Array (something passed by reference), this doesn't work. Talking specifically about `Object.defineProperty` since `get` will return whatever you define within it and if you try to change it's properties it won't behave like a normal JS "constant". – Sam Oct 05 '20 at 21:53
  • 1
    @Sam, nothing in JavaScript is passed by reference. [Everything is passed by value](https://stackoverflow.com/questions/42045586/whats-the-difference-between-a-boolean-as-primitive-and-a-boolean-as-property-o/42045636#42045636). – Scott Marcus Oct 05 '20 at 21:55
  • @Sam This will work for array and objects, do you have a specific example where it doesn't? – Anthony Garcia-Labiad Oct 05 '20 at 21:56
  • @ScottMarcus well... https://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference – Sam Oct 05 '20 at 22:04
  • @AnthonyGarcia-Labiad yes, if the `get` method is `() => {return {hello: 'hello'}}`, this will prevent you from being able to add/update methods and properties on the object since the `get` method always returns the exact same object. A JS constant doesn't work like that. A JS constant prevents you from reassiging the variable, but you should still be able to assign/reassign it's properties. With `defineProperty` used in this way, if you try to reassign `s.hello = 'goodbye'` it will not actually update the object. – Sam Oct 05 '20 at 22:08
  • I guess you could use a closure to make it work though. Something like: `function setT() {const hello = {hello: 'hello'}; Object.defineProperty(window, "t", { get: () => hello,set: () => { throw Error('s is a constant.') }});}` I hate writing code in these comments. – Sam Oct 05 '20 at 22:12
  • @Sam Ok I understand now. Yes you are correct, a closure would make it work. – Anthony Garcia-Labiad Oct 05 '20 at 22:17
  • @AnthonyGarcia-Labiad I see the in the defineProperty approach the scope of the deifned variable s is in all javascript files (maybe because of "window"), how can I change it to be just in the js file where it was defined? – Abdallah Barghouti Oct 05 '20 at 22:45
  • @Sam Did you read the link you posted. The post states "copy of a reference". A "copy" of a reference is not the same thing as "passing" by reference. Passing by reference means exactly that, the original reference is passed - that is not what happens in JavaScript. In JS a copy of the reference is passed. These are two very different things and lead to different behaviors when used. As such, what I said (and my answer that I linked to) are correct, everything is passed by value (a copy) in JavaScript. – Scott Marcus Oct 05 '20 at 23:23
  • @Sam And, if you didn't read the accepted answer of that post you shared it says quite clearly: *Specifically, when you pass an object (or array) you are (invisibly) passing a reference to that object, and it is possible to modify the contents of that object, but if you attempt to overwrite the reference it will not affect the copy of the reference held by the caller - i.e. **the reference itself is passed by value*** – Scott Marcus Oct 05 '20 at 23:26
1

Your only option is to store the value in the window. Just be sure to at least namespace your value, as it could conflict with something else already in the window:

// Create the namespace at the beginning of your program.
if (!window.MY_APP) {
  window.MY_APP = {};
}

window.MY_APP.s = 10;
code-gorilla
  • 2,231
  • 1
  • 6
  • 21
-2

It is possible to solve your problem by utilizing an anti-pattern. Be advised that I'm not advocating this approach, but from a pure "can you do it" perspective, any non-declared variable that is assigned in a function becomes a Global by default (of course this does not create a constant as you've asked, but thought I would show it anyway):

function foo(){
  bar = "baz";   // implicit Global;
}

foo();


// Show that "bar" was, in fact added to "window"
console.log(window.bar);  // "baz"
console.log(bar);  // "baz"
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Why rely on implicit globals when you can just make an explicit global? This is not a good solution or good advice to give, and nobody should write code this way. Most styles guides forbid this, most linters warn about it, and most developers would call this out as an error in a code review. – user229044 Oct 06 '20 at 15:42
  • @meagar So, apparently you didn't bother to read my answer (as a moderator, I would think you would before down voting or commenting). I was quite clear that I was only posting it as informational for those who perhaps didn't know that this is what happens and that I wasn't advocating the approach. I did not provide it as "advice" and called it out as an anti-pattern. – Scott Marcus Oct 06 '20 at 16:41