【问题标题】:javascript functional object scopesjavascript 功能对象范围
【发布时间】:2014-03-04 23:17:54
【问题描述】:

我在思考 javascript 函数式编程模式时遇到了一些麻烦,特别是因为它们与变量范围有关。我在网上找到的关于这个主题的大部分内容都很有帮助。但事情仍然没有点击。考虑以下示例:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="/d3.v3.min.js"></script>
</head>
<body>
<script type="text/javascript">
    function SimpleWidget(spec) {

        var instance = {};

        var headline, description;

        instance.render = function () {
            var div = d3.select('body').append("div");

            div.append("h3").text(headline);

            div.attr("class", "box")
                    .attr("style", "color:" + spec.color)
                    .append("p")
                    .text(description);

            return instance;
        };

        instance.headline = function (h) {
            if (!arguments.length) return headline;
            headline = h;
            return instance;
        };

        instance.description = function (d) {
            if (!arguments.length) return description;
            description = d;
            return instance;
        };

        return instance;
    }

    var widget = SimpleWidget({color: "#6495ed"})
            .headline("Simple Widget")
            .description("This is a simple widget demonstrating functional javascript.");
    widget.render();
</script>
</body>
</html>

此模式很有用,因为它封装了可重用的 sn-p 代码。我们可以重构 SimpleWidget() 函数以获取元素 id,并使用一些简单的 jquery 代码更新渲染函数以更新 dom,从而能够使用它来更新任何给定的元素。有用,但我对它的工作原理没有深入了解。

widget 对象如何访问传入的变量 'spec' ({color: "#6495ed"})?查看方法链接,我希望“小部件”只有 3 个函数,但它也可以访问 simpleWidget() 函数的内部范围变量。

通过 chrome 调试器运行它显示小部件对象内的渲染函数有一个“函数范围”,其中包含描述、实例和规范变量;但这似乎神奇地发生了。我不清楚这些内部变量在将它们的包含函数分配给变量并随后调用它的函数时是如何传递的。

当标题和描述函数都返回实例对象时,让我特别困惑的是 render() 函数如何能够访问 spec 变量。我希望有人可以在这里为我指明正确的方向。

【问题讨论】:

标签: javascript closures scope


【解决方案1】:

这正是闭包的作用。当您在 javascript 中定义一个函数时,它将永远可以访问其父范围内的变量。因此,当您将小部件定义为返回的实例时,您已分配为小部件属性的那些函数“知道”规范变量,因为它在父范围内可用。

换句话说,SimpleWidget 被调用,spec 变量被绑定到你传入的参数,然后你定义一个新函数并将它分配给变量render。即使在 SimpleWidget 返回之后,该函数也会始终知道来自父作用域的变量 spec。

【讨论】:

    【解决方案2】:

    实际上,在全局范围内创建的函数可以相互调用。一个函数有一个符号表,它告诉它在内存中的哪里查找它的变量,并且在该函数中定义的每个函数都会获得一个返回到它的链接,以便它们可以引用它们的对等点。

    如果您稍后从 SimpleWidget() 外部更改了 render(),它将没有此链接,并且不知道如何访问“规范”。由于您的示例中的 render() 是在 SimpleWidget() 中定义的,因此它具有指向创建它的 SimpleWidget() 调用的链接,并且可以访问与该调用相关的内存位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 2015-10-12
      • 1970-01-01
      • 2013-05-29
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多