1

Fairly new to NodeJs (however not to Javascript) and I think it is great, not in all aspects but that is not the subject of the question.

Found this 'feature' by accident, actually it is exactly what I want however don't know it is legit or a bug. What I did in an include file:

// var <- var is now a comment
 ksNone         = 0,
 ksAltKey       = 1, 
 ksCtrlKey      = 2,
 ksShiftKey     = 4; 
 ......
 .......

When traversing the global object in the main file, with code below ...

code:

require( './lib/mycode.js' );

for( var p in global )
{ console.log( p ); }

.... you will finally see:

output:

........ <- many other vars
 ........
 ........
ksNone
ksAltKey
ksCtrlKey
ksShiftKey

Made me thinking, it not easy to include a file with a bunch of functions for general purpose. For example, I have some functions to validate strings and numbers and all kind of other stuff that doesn't need to be in a namespace or class. Normally, to include such functions you have to specify exports for it or include it in a hacky way via fs and eval() - see also this question.

I tried the the following:

code:

 ksNone         = 0,
 ksAltKey       = 1, 
 ksCtrlKey      = 2,
 ksShiftKey     = 4,
 isNumber = function( i ) 
 {
   return typeof i === 'number' && isFinite(i) && !isNaN(i);
 },
 isValidNumber = function( i, iMin, iMax )
 {
  if( !isNumber( i ) )
   { return false; }

  if( isNumber( iMin ) && i < iMin ) 
   { return false; }

  if( isNumber( iMax ) && i > iMax ) 
   { return false; }

  return true;  
 }, 
isString = function( a ) 
 {
   return ( typeof a === 'string' || ( a instanceof String ));
 }, 
 isValidString = function( s, iMinLen, iMaxLen )
 {
   if( isString( s ) )
   {
     var iLen   = s.length,
         bIsMin = ( isNumber( iMinLen ) && iMinLen >= 0 )?(iLen >= iMinLen):(iLen > 0),
         bIsMax = ( isNumber( iMaxLen ) && iMaxLen >= 0 )?(iLen <= iMaxLen):(iLen > 0);

     return ( bIsMin && bIsMax );    
   }

   return false;
 };

And traversing again will now output:

output:

 ........ <- many other vars
 ........
 ........
ksNone
ksAltKey
ksCtrlKey
ksShiftKey
isNumber
isValidNumber
isString
isValidString

Once included, because it is now in the global scope, I can do this everywhere:

code:

var test = "yes"

if( isValidString( test ) ) // call the global function
 { console.log( "String is valid" ); }

output:

String is valid

questions:

Normally it is not a good idea to left out declaration stuff such as var (it doesn't work in strict mode - "use strict"; ) however in this case it seems to be very handy because you don't need to specify exports or use a hacky way to include it and those functions are globally accessable without a namespace or const/var require declaration.

What actually happen when you include a file? Scans the NodeJs core consts, vars, functions to keep it private? Is it legit to use or is it a bug? A do or don't, what do you think?

Codebeat
  • 6,501
  • 6
  • 57
  • 99
  • Run your code in `strict` mode and then the interpreter will not allow you to make mistakes like that. That is legacy Javascript (that doesn't require declaring before use) and is indeed bad, not a bug, but superceded/fixed by running your code in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). Do NOT do what you're doing. Implicit globals are a bad thing. In modules with node.js, globals are not needed at all. – jfriend00 Aug 12 '18 at 00:31
  • @jfriend00: That's what i notice in the question already, about strict mode. – Codebeat Aug 12 '18 at 00:32
  • Well, I'm telling you that it's not a bug in the interpreter (it is intended to work that way in non-strict mode), but that its a bad practice to use. So, just run your code in strict mode and it will not let you do that, even accidentally. And, don't be tempted to use globals to avoid proper module imports/exports. node.js modules require explicit import and export for many good reasons and good coding practice will not use globals. – jfriend00 Aug 12 '18 at 00:34

1 Answers1

0

Normally it is not a good idea to left out declaration stuff such as var (it doesn't work in strict mode - "use strict"; ) however in this case it seems to be very handy because you don't need to specify exports or use a hacky way to include it and those functions are globally accessable without a namespace or const/var require declaration.

The node.js module system encourages:

  1. Enhanced ability to reuse or share modules
  2. Well defined interface between modules, done the same way by everyone and every module
  3. Enhanced testability of modules
  4. No global symbol conflicts
  5. Code privacy within module scope (harder to hack or unintentionally mess with things)
  6. Explicit dependencies between modules

Globals can cause various problems:

  1. Accidental naming conflicts in the global namespace
  2. Implicit dependencies (module requires some unstated global condition to exist before it works properly)
  3. Things can be overwritten or hacked or just generally messed with in ways the author does not intend

The only downside of doing it the proper export/import way is a slight bit more typing to import or export interfaces between modules.

So, here are my recommendations related to your question:

  1. Do not use globals for interfacing between modules. Just get used to a slight bit more typing to properly import and export things. It will pay off in the short and long run.
  2. Run your code in strict mode, thus requiring that all variables be explicitly declared and no ability to have an accidental or implicit global. These are accidents just waiting to happen. Avoid them. Declare all variables.
  3. Use let or const to specify/limit the scope of your variable, not even var.

What actually happen when you include a file? Scans the NodeJs core consts, vars, functions to keep it private? Is it legit to use or is it a bug? A do or don't, what do you think?

Implicit globals don't get created until the line of code that first assigns to them is executed. There's no advanced scanning. They get created upon demand. But, don't use that - don't rely on it. This is not a bug. It is a legacy Javascript design decision (most would consider it a bad design decision) that was done on purpose. But, avoid it. Don't program that way on purpose and use strict mode so that the interpreter will point out any accidental variables that you forgot to declare.

Inside a function, all var declared variables are created at the time the function is called. This is called variable hoisting" and is a feature of the language. When the interpreter compiles the function, it makes a note of all var declarations within the function so that when it runs that function, it can pre-create them each time the function starts running.

let and const variables are only available within the block scope they are created. var is function scoped, let and const are blocked scoped. Unlike var, you cannot reference a let or const variable within the scope until the line of code containing its definition has run (a further safety over strict mode).

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Hai, thanks for the nice answer. I like the rules and goals you describe here however I think it is in some aspects a fairytale because javascript is not solid enough to ensure security. I mean, in PHP for example, you cannot override things once defined (for example a function), in Javascript you easily can with some ugly malicious but valid code. If an attacker know it is Node.js and break in, a smart attacker can access and manipulate everything (in run-time!). The flexibility of javascript is a weak point when it comes to code security. .................. (see next)...... – Codebeat Aug 12 '18 at 13:26
  • .....(continue)...... The global name conflicts story is true however can be easily avoided by using a prefix. That's what I use in PHP to extend the default functions with global functions and these functions can be used in classes. I wonder what will happen when you override/inject an object namespace, if it is possible anyway, will try this later. So yeah, I dunno about their security goals because the main weakness is javascript itself with the flexibility. – Codebeat Aug 12 '18 at 13:26
  • Also the abuse of countless exceptions in Node.js is a weakness. You can easily shutdown the server by assigning a value to a constant. Rediculous. They need to design a notice and warning feature like in PHP. For example at the URL class, assign an invalid url and there is again an exception, Why an exception at an invalid string. it is very easy to shutdown the server which is a very weak and unreliable construction. – Codebeat Aug 12 '18 at 13:43
  • @Codebeat - Please don't just rant here. I'm attempting to help you and I'm not responsible for any of the design decisions in node.js or Javascript or even know why they are the way they are so ranting does you no good at all. Personally, I'd much rather program in node.js/Javascript than PHP any day so maybe once you really learn the environment you'll start to understand some of that. I"d strongly suggest you learn the spirit and advantages of modules and stop using globals. – jfriend00 Aug 12 '18 at 16:11
  • I didn't say you are responsible for this and it doesn't meant to be a rant, glad with your nice answer. maybe you are right this is not the best place to discuss it. I really like NodeJs but there are also very strange things / policies that actually doesn't fit the language (very well). – Codebeat Aug 12 '18 at 20:00