代码之家  ›  专栏  ›  技术社区  ›  Codebeat

js:意外省略的var声明通过全局对象、bug或feature公开所有变量?

  •  1
  • Codebeat  · 技术社区  · 7 年前

    偶然发现了这个“功能”,其实它正是我想要的,但是不知道它是合法的还是一个bug。我在include文件中做了什么:

    // 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()以一种复杂的方式包含它-另请参见 question .

    我尝试了以下方法:

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

    当你包含一个文件时会发生什么?扫描NodeJs核心常量、变量、函数以使其保持私有?是合法使用还是虫子?做还是不做,你怎么看?

    1 回复  |  直到 7 年前
        1
  •  0
  •   jfriend00    7 年前

    通常情况下,不考虑声明内容,比如var(它在strict模式下不工作-“use strict”;)但是在这种情况下,它似乎非常方便,因为您不需要指定导出或使用一种黑客方法来包含它,而且这些函数在没有名称空间或const/var require声明的情况下是全局可访问的。

    node.js模块系统鼓励:

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

    1. 全局命名空间中的意外命名冲突
    2. 隐式依赖关系(模块需要在其正常工作之前存在一些未声明的全局条件)
    3. 事情可以被改写,被黑客攻击,或者只是以作者不打算的方式被破坏

    正确的导出/导入方式的唯一缺点是在模块之间导入或导出接口时稍微多输入一点。

    所以,以下是我对你的问题的建议:

    1. 在严格模式下运行代码,因此要求显式声明所有变量,并且不能有意外或隐式全局变量。这些都是等待发生的意外。避开他们。声明所有变量。
    2. let const 指定/限制变量的范围,甚至 var .

    隐式全局变量直到第一次分配给它们的代码行被执行后才被创建。没有高级扫描。它们是按需制造的。但是,不要用它-不要依赖它。这不是虫子。这是一个传统的Javascript设计决策(大多数人会认为这是一个糟糕的设计决策),是故意的。但是,避免它。不要故意那样编程 strict 使解释器指出您忘记声明的任何意外变量。

    在函数内部,所有 风险价值 函数中的声明,以便在它运行该函数时,可以在每次函数开始运行时预创建它们。

    变量仅在创建的块范围内可用。 是函数作用域, 常量 已锁定作用域。不像 ,不能引用 范围内的变量,直到包含其定义的代码行运行为止(更安全的严格模式)。

    推荐文章