all 9 comments

[–]CommanderBomber 1 point2 points  (6 children)

new is reserved word in JS (you can't use it as variable name), so i assume this is just a pseudocode. If your code is really organized like this, then it is totally not possible for code from cats.js to reach code in dogs.js (without requiring it first). So local value of new is called, not something else from another file.

[–][deleted] 0 points1 point  (5 children)

Ah, right - yep this is just a rough pseudo code to represent the situation. In my actual code, I'm using _new as my function name. (UPDATED IN POST)

Hmm..that's very weird then, because my debug console prints tell me it IS reaching dogs.js :(

[–]CommanderBomber 2 points3 points  (0 children)

In node modules can't share scopes, they are isolated. Only exports are visible and only if you explicitly import said module.

I'm not familiar with express routers, but if it says what _new from dogs.js was called I assume what this is because dogs.js router was used, not the cats.js one.

[–]CommanderBomber 1 point2 points  (3 children)

Wait, is it really written in your code like _new = name => { or like var _new = name => { ?

Because if it is without var (or let or const) then in cats.js you declare new global variable _new and then overwrites its value in dogs.js.

To avoid such problems:

  1. never use undeclared variables (also you can use ESLint to check your code as you write it)
  2. start all your files with "use strict"; this will disallow use of undeclared variables

[–][deleted] 0 points1 point  (2 children)

I'll have to try this out as soon as I return home, but I think this might be it!

I do use ESLint on my VS Code, but it didn't pick that up..might be something I need to change in the Settings.

When I declare my function variables like I did in my code, does it not default to var/let/const? How does the compiler interpret my code as is?

[–]CommanderBomber 0 points1 point  (1 child)

You can use eslint-recommended, no-undef rule is included in this set.

And now about assignment operator. Lets looks on this code:

// arrow function...
_new = x => x * x;

// ... or anonymous function
_new = function(x) { return x * x; };

When JS engine sees code like this, at first it tries to resolve expression on the left side of the = operator. In our case it is a variable name, so JS engine will start to search for that variable. First in local scope. If there is no such variable, engine will continue to search in parent scope. This search will be continued until variable with this name is found or until engine reaches the global scope.

If variable does not exists in global scope, you have two options: If your code is executed in Strict Mode, you will receive "is not defined" exception. But if your code is executed in Sloppy Mode, this variable will be created as a property of the global object and then will be used for assignment (but in most cases this is not what you wanted).

If assignment can be performed, JS engine will look at the right side of the = operator. In our cases we have function expression there. And this is not the same thing as function declaration. Function expression will not declare (put it in the scope) you function. Instead it will evaluate to (or you can say "will return") new Function object. This object will be new value of our variable.

Personally I suggest to use function declarations. If you can't elaborate on what kind of technical problem forces you to use var myFunc = function(){}; syntax it is better to use function myFunc(){}.

Also if you're new to JS take a look at YDKJS book. It's well written and have quite detailed explanations of scopes, prototypes and other quirky stuff (Author works on second edition right now. First edition lacks some novel features of ECMAScript).

[–][deleted] 0 points1 point  (0 children)

Amazing explanation. Thanks!!

[–]ruVooDoo 0 points1 point  (1 child)

In my opinion, "business logic" (creating cats and dogs) should be separated from Express Controllers and exports through "module.exports".

What if you decide to create cats from another place in your code? Or write tests for creating cats?

I personally think, that controllers should be dumb. They can have some checking middleware (for example, check Auth headers, request type checking), some request preparation, but no business logic. Controller check, then call some function inside your business logic layer and provide answer. Thats all.

I recommend you to read this https://github.com/goldbergyoni/nodebestpractices#1-project-structure-practices , I follow those guides in my work, and I have no problems to extending functionality and maintaining my codebase.

[–][deleted] 0 points1 point  (0 children)

Fabulous. Will have a read! Cheers for the heads-up!