如何声明一个函数:作为一个单独的函数或在同一个函数中

时间:2014-04-18 14:46:50

标签: javascript node.js

Hello Stackoverflow人员,

问题是代码风格和代码可维护性,而不是搜索某些错误。

我们假设我正在为node.js创建一些模块。这个模块只导出一个对象,让我们调用这个对象" FileParser"。在文件解析期间,可以有不同的预处理功能。它们非常独特,我不打算在应用程序的其他部分重用它们。

因为,这个模块只导出一个函数 - 我的问题是下一个

如果我有这个模块的一些实用函数,我应该在导出的函数中定义这个函数,还是应该在这个函数之外定义它们。

基本上 - 这个:

var FileParser = function(){
}

FileParser.prototype.methodToExport = function(){
  var utilityFunction = function(){
    //do some work, maybe even return values
  }

  //do some other work.
  utilityFunction();

  //do more other work
}
module.exports.FileParser = FileParser;

或者这个:

var FileParser = function(){
}

FileParser.prototype.methodToExport = function(){
  //do some work before calling function
  utilityFunction();
  //do more and more work after calling function
}

function utilityFunction(){
 //body of function goes here, maybe even returning some value
}
module.exports.FileParser = FileParser;

更具可读性,特别是在实用功能很少的情况下。

谢谢, -D

4 个答案:

答案 0 :(得分:4)

如果utilityFunction未用作闭包(即它不访问methodToExport函数中声明的变量),则没有充分的理由在其他函数内声明它。

把它放在外面,它会使methodToExport缩短(因此更具可读性)。

由于它位于“本地”模块范围内,因此您甚至无需担心全局命名空间污染。如果实用程序功能的数量增加,您可以考虑对它们进行适当的分组,例如通过使用揭示模块模式。

答案 1 :(得分:0)

在第一种情况下,每次调用methodToExport时都会声明您的函数,在第二种情况下,您将具有全局函数。也许你可以使用某种封闭:

FileParser.prototype.methodToExport = function() {
    function utilityFunction () { 
        //do some work, maybe even return values
    }
    return function () { // This is the real function, the one which will be export!
        //do some other work
        utilityFunction () ;
        //do more other work
    } ;
} () ;

也许有更好的方法,但我会做那样的事情!

答案 2 :(得分:0)

JavaScript足够灵活,可以允许这样的事情,声明如下,但在我看来并不是一个好的实践。

var FileParser = function(){

}

FileParser.prototype.methodToExport = function(){
    var utilityFunction = function(){
        //do some work
    }
    utilityFunction();
}

module.exports.FileParser = FileParser;

您正在声明并调用函数内部,但更明确的是在FileParser对象的声明中执行此操作。

所以,你有很好的宣传模式Revealing Pattern,由Addy Osmani提出。

var FileParser = function(){
    var utilityOne = function(){
    }

    this.methodToExport = function(){
       // do some work 
       utilityOne();
    }
}

module.exports.FileParser = FileParser;

这可以隐藏一些实用功能作为一种封装,只显示外面的重要功能。

答案 3 :(得分:0)

你没有问过这个问题,但是我建议你把你的代码放在IIFE里面,这样在顶级闭包中只有一个变量,如下所示:

module.exports.FileParser = (function(){
    var FileParser = function(){};
    // Do your stuff
    return FileParser;
})();

这样可以节省为FileParser创建全局变量的需要。

现在关于你问过的问题 - 如果在导出的函数中或在其外部定义效用函数 - 我的答案取决于你是仅导出单个函数还是多个函数。在你的情况下,因为你只导出一个函数,我的答案是,只要你有一个选择,我更喜欢外部定义的效用函数,因为它的闭包范围更小。 “只要你有选择权”,我的意思是你的效用函数没有使用methodToExport中定义的任何东西。

module.exports.FileParser = (function(){
    var FileParser = function(){};
    var utilityOne = function(){};

    FileParser.prototype.methodToExport = function(){
        // do some work 
        utilityOne();
    }
    return FileParser;
})();

较小的闭合范围在大多数情况下并没有太大的区别,但以下是一个例子。

module.exports.FileParser = (function(){
    var FileParser = function(){};


    FileParser.prototype.methodToExport = function(){
        var longArray = [ /* ... */ ];
        var utilityOne = function(){
            setInterval(function(){
                console.log("Hello");
            },1000);
        };
        utilityOne();
    }
    return FileParser;
})();

在上面的示例中,longArray位于utilityOne()的封闭中,即使不需要它。 setTimeout对longArray的引用可以防止它被垃圾回收。

module.exports.FileParser = (function(){
    var FileParser = function(){};
    var utilityOne = function(){
        setInterval(function(){
            console.log("Hello");
        },1000);
    };

    FileParser.prototype.methodToExport = function(){
        var longArray = [ /* ... */ ];
        utilityOne();
    }
    return FileParser;
})();

utilityOne()定义移出方法定义会缩小其闭包范围,并允许对longArray进行垃圾回收。