question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

no-param-reassign and no-use-before-define

See original GitHub issue

So I just spent a few hours setting up ESLint for the first time with the AirBnB settings and let me just say that it was worth it. My code looks much nicer and it helped me find some improvements.

the rules no-param-reassign and no-use-before-define still need to be followed in the code but I’m not sure if I agree with those rules, or maybe I don’t understand how to deal with them yet.

no-use-before-define makes it so you cannot follow the ‘top-to-bottom’ principle from Clean Code because it complains when you do:

const higherLevelFunction = () => {
       // stuff

       lowerLevelFunction(); 
       // [eslint] 'lowerLevelFunction' was used before it was defined. (no-use-before-define)

       // more stuff
};
const lowerLevelFunction = () => {
       // compute something
};
// Bottom of file...
higherLevelFunction();

no-param-reassign makes it so you cannot do stuff like:

someNodeList.forEach((el) => {
      el.style.display = 'none';
});
// [eslint] Assignment to property of function parameter 'ct'. (no-param-reassign)

Are these things intentional? And if they are, how can I comply with these rules?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:8
  • Comments:12

github_iconTop GitHub Comments

10reactions
dtinthcommented, Jun 21, 2019

Adding this comment just for reference, so people don’t feel too guilty disabling the no-use-before-define rule.


Here’s an example case where we had to disable the rule no-use-before-define. This came from one of our scripts doing some deployments:

function main() {
  deployApplication();
  invalidateCDNCache();
  verifyDeployment();
  notifyTeam();
}

function deployApplication() {
  deployAssetFiles();
  deployIndexFile();
}

function deployAssetFiles() {
  /* 20 lines of code */
}

function deployIndexFile() {
  /* 20 lines of code */
}

function invalidateCDNCache() {
  /* 30 lines of code */
}

function verifyDeployment() {
  /* 15 lines of code */
}

function notifyTeam() {
  /* 10 lines of code */
}

main();

In terms of readability, having main at the top means that a reader can understand what the script does by reading just the first 6 lines. Compare it to this:

// 🤔 Where will this be used? Will have to read more to find out...
//    1 thing to keep track on my head.
function deployAssetFiles() {
  /* 20 lines of code */
}

// 🤔 Where will this be used? Will have to read more to find out...
//    2 things to keep track on my head.
function deployIndexFile() {
  /* 20 lines of code */
}

// 🤔 Where will this be used? Will have to read more to find out...
//    3 things to keep track on my head.
function deployApplication() {
  // 🤔 Oh, they are used here! 1 thing left to keep track of.
  deployAssetFiles();
  deployIndexFile();
}

// 🤔 Where will this be used? Will have to read more to find out...
//    2 things to keep track on my head.
function invalidateCDNCache() {
  /* 30 lines of code */
}

// 🤔 Where will this be used? Will have to read more to find out...
//    3 things to keep track on my head.
function verifyDeployment() {
  /* 15 lines of code */
}

// 🤔 Where will this be used? Will have to read more to find out...
//    4 things to keep track on my head.
function notifyTeam() {
  /* 10 lines of code */
}

function main() {
  // 🤔 Oh, they are used here!
  deployApplication();
  invalidateCDNCache();
  verifyDeployment();
  notifyTeam();
}

main();

People don’t put table of contents at the end of the book. I believe the same principle applies to code as well.


I noticed that the rule is not documented in the README file… would be great if the rules and rationale are also documented there.

5reactions
tunnckoCorecommented, Jul 10, 2018

@ljharb harming readability

absolutely not.

The “from top to bottom” is exactly about that. When you getting started with some package or code, you open the file, starting to read from the top (or search where the module.exports is) then reading line by line you are seeing bar(), ooh okey, you scroll down and the next function declaration is exactly what you need. When you finish reading the bar you eventually goes up to where you first found it, or continue the same way to the bottom.

This “principle” is absolutely stunning and is always helpful and everyone should trying to follow. I’m doing this for years and reading this way for years, and it is a huge boost.

Start reading this for example https://github.com/olstenlarck/hela/blob/v3-major/packages/core/src/index.js#L214-L219 (the main thing is the action() method). One may say “you start from the bottom”, no, it’s just bigger convention here in nodejs, but not applies to another languages.

You start reading the action() method, you seeing createHandler() cal, but also visually noticed (maybe i’m the freak, cuz have amazing photographic memory) that in few lines later there is also stringActionWrapper() - okey, scroll down - ha! it’s exactly after the hela() declaration. You started reading createHandler() and you immediately seeing one more call to stringActionWrapper(), so you think hm, okay i’m going to this after i finish with that. But hA! wat a surprise!? It’s exactly the next function declaration. After you read the stringActionWrapper declaration, you noted the handleChaining declaration, and you going above back to where you start - the action() method, you are seeing handleChaining() and createActionWrapper() so you go to them and you are ready.

That’s why i willl always use function declarations instead of some funky new syntaxes and ways like const foo = () => {}.

This rule is absolutely great. That’s why i always change it a bit

'no-use-before-define': ['error', { 
+ functions: false, 
  classes: true, 
  variables: true }]
'no-use-before-define': ['error', { 
- functions: true,
  classes: true,
  variables: true }]
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to avoid no-param-reassign when setting a property on a ...
Personally, I would just use the "no-param-reassign": ["error", { "props": false }] approach a couple of other answers mentioned. Modifying a property of...
Read more >
no-param-reassign - ESLint - Pluggable JavaScript Linter
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
Read more >
What the Heck is the deal with no-param-reassign
When a variable holds a primitive (Number or String) and you re-assign its value your pointing it to a new memory location. view...
Read more >
Lint - Ant Design Pro
Don't use it before the definition, this needless to say, it will directly error. no-param-reassign does not support fix. Do not assign ...
Read more >
Javascript – How to handle eslint no-param-reassign rule in ...
However, when I use reduce to build out an object (empty object as initialValue ), I find myself needing to modify the accumulator...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found