https://eslint.org/docs/latest/rules/no-use-before-define We should switch to `variables: false` as the default config for `no-use-before-define`. This setting still makes it an error to use variables from the same scope before they're defined, as well variables from a synchronous parent scope (`while` example below). The only thing it allows is accessing a variable from inside the function, even when that function is defined before the variable. This is rarely a real error, and when it is, it's very obviously broken, because it means a function is being called (synchronously, directly) from the same scope it is defined in, but before the variables are defined. ``` /* eslint no-use-before-define: ["error", { "variables": false } ] */ let foo; function f() { alert(foo + bar + baz); // allowed } while (Math.random() < 0.5) { alert(foo + bar + baz); // error } alert(foo + bar + baz); // error foo = 1; var bar = 2; let baz = 3; f(); ``` [ESLint playground link.](https://eslint.org/play/#eyJ0ZXh0IjoiLyogZXNsaW50IG5vLXVzZS1iZWZvcmUtZGVmaW5lOiBbXCJlcnJvclwiLCB7IFwidmFyaWFibGVzXCI6IGZhbHNlIH0gXSAqL1xuXG5sZXQgZm9vO1xuXG5mdW5jdGlvbiBmKCkge1xuICBhbGVydChmb28gKyBiYXIgKyBiYXopOyAgICAgIC8vIGFsbG93ZWRcbn1cblxud2hpbGUgKE1hdGgucmFuZG9tKCkgPCAwLjUpIHtcbiAgYWxlcnQoZm9vICsgYmFyICsgYmF6KTsgICAgICAvLyBlcnJvclxufVxuXG5hbGVydChmb28gKyBiYXIgKyBiYXopOyAgICAgICAgLy8gZXJyb3JcblxuZm9vID0gMTtcbnZhciBiYXIgPSAyO1xubGV0IGJheiA9IDM7XG5cbmYoKTtcbiIsIm9wdGlvbnMiOnsiZW52Ijp7ImJyb3dzZXIiOnRydWV9LCJydWxlcyI6e30sInBhcnNlck9wdGlvbnMiOnsiZWNtYUZlYXR1cmVzIjp7fSwiZWNtYVZlcnNpb24iOjIwMTUsInNvdXJjZVR5cGUiOiJzY3JpcHQifX19) The reason for changing: the [workaround we use when we actually need to use a global](https://searchfox.org/mozilla-central/rev/ddde3bbcaf/toolkit/components/extensions/ExtensionParent.sys.mjs#73-75) variable from a function defined earlier is: just stick `let foo;` at the top of the file, which shuts up the linter, but provides false sense that this is somehow "safe". The _natural_ way to do this is to declare and initialize the variable at the end of the file, which makes it more obvious that it might not be initialized if the function is called before the before the variable declaration (and using the `var`, which is very uncommon today, only reinforces that point). I've never liked this pattern, but now we also have a good reason to get rid of it: TypeScript type inference works much better with the natural way of writing code. Object are fully typed when [initialized during definition all at once](https://phabricator.services.mozilla.com/D196386#C7179214NL2126). (and btw, while we're changing the defaults, we should also use `function: false`, as functions are actually hoisted, and there's nothing wrong or unsafe with calling a function declared later in the file)
Bug 1870205 Comment 0 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
https://eslint.org/docs/latest/rules/no-use-before-define We should switch to `variables: false` as the default config for `no-use-before-define`. This setting still makes it an error to use variables from the same scope before they're defined, as well variables from a synchronous parent scope (`while` example below). The only thing it allows is accessing a variable from inside the function, even when that function is defined before the variable. This is rarely a real error, and when it is, it's very obviously broken, because it means a function is being called (synchronously, directly) from the same scope it is defined in, but before the variables are defined. ``` /* eslint no-use-before-define: ["error", { "variables": false } ] */ let foo; function f() { alert(foo + bar + baz); // allowed } while (Math.random() < 0.5) { alert(foo + bar + baz); // error } alert(foo + bar + baz); // error foo = 1; var bar = 2; let baz = 3; f(); ``` [ESLint playground link.](https://eslint.org/play/#eyJ0ZXh0IjoiLyogZXNsaW50IG5vLXVzZS1iZWZvcmUtZGVmaW5lOiBbXCJlcnJvclwiLCB7IFwidmFyaWFibGVzXCI6IGZhbHNlIH0gXSAqL1xuXG5sZXQgZm9vO1xuXG5mdW5jdGlvbiBmKCkge1xuICBhbGVydChmb28gKyBiYXIgKyBiYXopOyAgICAgIC8vIGFsbG93ZWRcbn1cblxud2hpbGUgKE1hdGgucmFuZG9tKCkgPCAwLjUpIHtcbiAgYWxlcnQoZm9vICsgYmFyICsgYmF6KTsgICAgICAvLyBlcnJvclxufVxuXG5hbGVydChmb28gKyBiYXIgKyBiYXopOyAgICAgICAgLy8gZXJyb3JcblxuZm9vID0gMTtcbnZhciBiYXIgPSAyO1xubGV0IGJheiA9IDM7XG5cbmYoKTtcbiIsIm9wdGlvbnMiOnsiZW52Ijp7ImJyb3dzZXIiOnRydWV9LCJydWxlcyI6e30sInBhcnNlck9wdGlvbnMiOnsiZWNtYUZlYXR1cmVzIjp7fSwiZWNtYVZlcnNpb24iOjIwMTUsInNvdXJjZVR5cGUiOiJzY3JpcHQifX19) The reason for changing: the [workaround we use when we actually need to use a global](https://searchfox.org/mozilla-central/rev/ddde3bbcaf/toolkit/components/extensions/ExtensionParent.sys.mjs#73-75) variable from a function defined earlier is: just stick `let foo;` at the top of the file, which shuts up the linter, but provides false sense that this is somehow "safe". The _natural_ way to do this is to declare and initialize a variable later in the file, which makes it more obvious that it might not be initialized if the function is called before the variable declaration (and using the `var`, which is fairly uncommon today, only reinforces that point). I've never liked this pattern, but now we also have a good reason to get rid of it: TypeScript type inference works much better with the natural way of writing code. Object literals are fully typed when [initialized during definition all at once](https://phabricator.services.mozilla.com/D196386#C7179214NL2126). (and btw, while we're changing the defaults, we should also use `function: false`, as functions are actually hoisted, and there's nothing wrong or unsafe with calling a function declared later in the file)