什么是JavaScript中嵌套函数的需要和使用

Whats the need and use of nested functions in JavaScript

我理解嵌套函数是什么,但我不明白为什么我们甚至首先需要嵌套函数。 是否存在只能通过在JavaScript中使用嵌套函数来解决的问题。 我看到的所有创建嵌套函数的示例都可以在不在函数内部创建函数的情况下进行编码,并且结果相同。 那么哪个问题需要创建嵌套函数,并且只能通过使用嵌套函数来有效地解决。


嵌套函数的核心重要性是范围生成。我们需要JavaScript中的嵌套函数和作用域来实现以下功能。

  • 无污染的全局命名空间
  • 功能模块化
  • 封装模块的私有内部工作
  • 防止标识符在不同脚本之间发生冲突
  • 由于嵌套作用域内的变量有资格进行缩小,因此脚本大小较小。
  • 它加快了标识符解析过程
  • 这是一个示例模块,显示函数嵌套和范围提供的封装功能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    var notificationService = (function ($, toastr, undefined) {
        var _externals = {},
            _jqExtend = $.extend;

        /*
         * Private Methods
         */

        function _showMessage(params) {
            params = params || {};
            toastr.remove();

            if (typeof (params.title) ==="undefined")
                toastr[params.method](params.msg);
            else
                toastr[params.method](params.msg, params.title);
        }

        /*
         * Public Members
         */

        _externals.clear = function () {
            toastr.remove();
        };

        _externals.showError = function (params) {
            params = params || {};

            _jqExtend(params, {
                method:"error"
            });

            _showMessage(params);
        };

        _externals.showInfo = function (params) {
            params = params || {};

            _jqExtend(params, {
                method:"info"
            });

            _showMessage(params);
        };

        _externals.showSuccess = function (params) {
            params = params || {};

            _jqExtend(params, {
                method:"success"
            });

            _showMessage(params);
        };

        _externals.showWarning = function (params) {
            params = params || {};

            _jqExtend(params, {
                method:"warning"
            });

            _showMessage(params);
        };

        return _externals;
    })(jQuery, toastr);

    上面的代码使我们有能力控制暴露的内容。在此特定情况下,通过引用notificationService对象将所有附加到_externals对象的成员公开给全局名称空间。在不使用作用域的情况下,内部成员(_jqExtend和_showMessage)也将附加到窗口对象,并增加浏览器解析标识符引用所需的工作量。


    这不是关于效率,而是关于范式。如果您使用脚本范例,您可以毫无后顾之忧地编写代码。如果使用经典范例,则需要定义类,但不需要嵌套函数。不过,在脚本和经典中,如果您愿意,可以使用嵌套函数。

    只有当你切换到功能范例,这是javascript的实际"原生"范例时,你才需要在某些情况下使用嵌套函数。

    只要你不使用函数式编程,你就不会充分利用javascript的强大功能。这是一个工厂的例子,它使用了一个无法完成的闭包(嵌套函数还有其他一些用途,而不仅仅是一个闭包):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function create(a, b)
    {
      function compute()
      {
        return a + b;
      }

      return {
       "compute": compute
      };
    }

    用户代码将执行:

    1
    f = create(19, 73);

    没有任何计算。比如说,计算这个需要花费很多时间,除非必要,否则你不想计算它。您现在可以将函数f传递给不属于您的其他代码(例如,jQuery事件处理程序代码):

    1
    $("#id").on("click", function () { console.log(f.compute()); });

    单击#id时将执行此f,但您无法执行任何操作。调用create()时,已嵌入参数ab

    这意味着您可以隐藏信息并利用上下文范围。想象一下,创建者和用户是两个不同的代码库,不是由同一个人编写的。或者ab是从其他代码库保存的秘密。

    查看我在上面的文字中散布的各种单词,以了解有关函数式编程的更多信息。

    If you want to know why we can't do without, then look at currying and monads, which are a fundamental parts of the functional paradigm. You need some mechanisms by which you can do these basic operations, otherwise the paradigm cannot be functional.


    首先,在编程中有几种方法可以完成任务但是在它们中我们必须选择一种在内存和执行时间方面高效且快速的方法。当你需要从主程序切换到子程序时,那么如果子程序的大小较小,上下文切换不仅仅是执行内联任务。如果大小较小则总体上是有益的,否则你总是有一个备用路径。而且嵌套函数可以访问它们上面的范围。它将减少将参数传递给函数并在程序中的其他地方重用它的麻烦。所有上述变量和函数都可以被这个嵌套函数访问并且可以更新它们。


    JavaScript变量可以属于本地或全局范围。

    全局变量可以通过闭包实现本地(私有)。

    JS中的函数类似于变量,因此如果可能希望使用嵌套函数供本地使用。

    Here's a good example