1

NodeJs 相当新(但不是 Javascript),我认为它很棒,不是在所有方面,但这不是问题的主题。

偶然发现了这个“功能”,实际上这正是我想要的,但不知道它是合法的还是错误的。我在包含文件中做了什么:

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

遍历主文件中的全局对象时,代码如下...

代码:

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

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

....你最终会看到:

输出:

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

让我想到,包含一个具有一堆通用功能的文件并不容易。例如,我有一些函数来验证字符串和数字以及不需要在命名空间或类中的所有其他类型的东西。通常,要包含此类功能,您必须为其指定导出或通过 fs 和 eval() 以一种骇人听闻的方式包含它 - 另请参阅此问题

我尝试了以下方法:

代码:

 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;
 };

现在再次遍历将输出:

输出:

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

一旦包含,因为它现在在全局范围内,我可以在任何地方这样做:

代码:

var test = "yes"

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

输出:

String is valid

问题:

通常,省略诸如var(它在严格模式下不起作用 - "use strict";)之类的声明内容不是一个好主意,但是在这种情况下,它似乎非常方便,因为您不需要指定导出或使用 hacky 方式包含它,这些函数无需命名空间或 const/var 要求声明即可全局访问。

包含文件时实际发生了什么?扫描 NodeJs 的核心 consts、vars、函数以保持私有?它是合法使用还是一个错误?做还是不做,你怎么看?

4

1 回答 1

0

通常,省略诸如 var 之类的声明内容不是一个好主意(它在严格模式下不起作用 - “使用严格”;)但是在这种情况下,它似乎非常方便,因为您不需要指定导出或者使用一种 hacky 方式来包含它,并且这些函数可以在没有命名空间或 const/var 要求声明的情况下全局访问。

node.js 模块系统鼓励:

  1. 增强重用或共享模块的能力
  2. 模块之间定义良好的接口,每个人和每个模块都以相同的方式完成
  3. 增强模块的可测试性
  4. 没有全局符号冲突
  5. 模块范围内的代码隐私(更难破解或无意中弄乱了东西)
  6. 模块之间的显式依赖关系

全局变量可能会导致各种问题:

  1. 全局命名空间中的意外命名冲突
  2. 隐式依赖(模块需要一些未说明的全局条件才能正常工作)
  3. 事情可以被覆盖或被黑客攻击,或者只是以作者不打算的方式被弄乱

以正确的导出/导入方式执行此操作的唯一缺点是在模块之间的导入或导出接口上需要输入更多内容。

因此,以下是与您的问题相关的我的建议:

  1. 不要使用全局变量来连接模块。只需习惯于输入更多内容即可正确导入和导出内容。它将在短期和长期内得到回报。
  2. 在严格模式下运行您的代码,因此要求所有变量都被显式声明并且不能具有意外或隐式全局。这些只是等待发生的事故。避开他们。声明所有变量。
  3. 使用letorconst指定/限制变量的范围,甚至不是var.

包含文件时实际发生了什么?扫描 NodeJs 的核心 consts、vars、函数以保持私有?它是合法使用还是一个错误?做还是不做,你怎么看?

在执行首先分配给它们的代码行之前,不会创建隐式全局变量。没有高级扫描。它们是根据需要创建的。但是,不要使用它——不要依赖它。这不是错误。这是一个有意做出的遗留 Javascript 设计决策(大多数人会认为这是一个糟糕的设计决策)。但是,避免它。不要故意以这种方式编程并使用strict模式,以便解释器指出您忘记声明的任何意外变量。

在函数内部,所有var声明的变量都是在调用函数时创建的。这被称为变量提升”并且是该语言的一个特性。当解释器编译函数时,它会记下var函数内的所有声明,以便在运行该函数时,它可以在每次函数启动时预先创建它们跑步。

let并且const变量仅在它们创建的块范围内可用。 var是函数作用域,let并且const是阻塞作用域。与 不同的是,在包含其定义的代码行运行之前var,您不能在范围内引用 a letorconst变量(比严格模式更安全)。

于 2018-08-12T04:31:37.870 回答