【问题标题】:Is this Javascript function efficient?这个Javascript函数有效吗?
【发布时间】:2012-04-20 06:36:27
【问题描述】:

我有一个节点列表,它们是 html li 元素

<ul id="nodesList">
   <li id="node_1">Node 1</li>
   <li id="node_2">Node 2</li>
   <li id="node_3">Node 3</li>
   <li id="node_4">Node 4</li>
   <li id="node_5">Node 5</li>
</ul>

我有一个管理这些节点的 javascript 函数

(function (nodesManager) {
    var nodes = [];
    nodesManager.requestNode = function(id) {
        if (nodes[id]) {
            return nodes[id];
        }

        nodes[id] = new Node(id);
        return nodes[id];
    }
} (window.nodesManager = window.nodesManager || {}));

var Node = function(id) {
    instance = this;

    var node = $("#node_" + id);

    this.changeName = function(newValue) {
        node.text(newValue);
    };

    // and other nodes specific functions

    var _properties = null;
    this.getProperties = function () {
        if (_properties !== null)
            return _properties;

        var response = null;
        $.ajax({
            cache: false,
            async: false,
            type: "GET",
            url: '/Nodes/NodeProperties', // json object { "dateCreated": "10 minutes ago", "createdBy": "Mike" }
            data: { node_Id: id },
            success: function (data, textStatus) {
                if (data.hasError) {
                    alert(data.message);
                } else {
                    response = data;
                }
             },
             error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert('ajax error');
             }
        });
        _properties = response;

        return _properties;
    };
        this.resetProperties = function () {
            _properties = null;
        };
    }


$("#nodesList").delegate("li", "click", function() {
    var node_Id = $(this).attr("id").replace("node_", "");

    var newNodeName = "I am a new value";
    nodesManager.requestNode(node_Id).changeName(newNodeName);
});

我的问题是,如果 Node 对象中的 changeName 函数会影响性能?

是否为用户选择的每个节点创建?

将它放在nodesManager 函数中以便只实例化一次更好吗?或者这没关系...

什么对我来说很重要

function getNodeCreatorUserName(id) {
    var properties = nodesManager.requestNode(id).getProperties();
    var userName = properties.createdBy;

    // do something with userName
};
function getNodeDateCreated(id) {
    var properties = nodesManager.requestNode(id).getProperties();
    var dateCreated = properties.dateCreated;

    // do something with dateCreated
};

getNodeCreatorUserName("1"); 
getNodeDateCreated("1");     // No server side call will be made because properties are already stored in Node object

【问题讨论】:

标签: javascript performance


【解决方案1】:

就您关心的性能问题(请记住,对于少量节点而言差异几乎不明显),您应该选择原型而不是闭包,因为它们(高达 >50%)更快,请参阅:

Javascript prototype operator performance: saves memory, but is it faster?

http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx

http://ejohn.org/blog/simple-class-instantiation/

【讨论】:

  • 我将使用原型来代替 Node 类。但是nodesManager闭包可以吗?
【解决方案2】:

Node 已在 window 中定义,您可能应该将其命名为其他名称。

试试这样的:

function MyNode (id) {
   this.node = $("#node_" + id);
}

MyNode.prototype.changeName = function(newValue) {
    this.node.text(newValue);
};

【讨论】:

  • 好的,如果我添加一个原型,我将如何选择单个节点?如果已经创建了对象,nodesManager 函数会注意不创建两个 Node 对象。当我想使用节点时,我总是必须创建一个 MyNode 对象? var node = MyNode("1"); node.changeName("随便");
  • @RaraituL new MyNode(id)。我假设您的 Node 函数是一个构造函数,因为它不返回任何内容并引用 thisthis 在您的 Node 函数中指的是什么?
  • 我不太擅长 javascript,这就是我想要学习的。实际上对我来说Node 是一个容器,其中包含页面中每个&lt;li&gt; 元素的数据。我还使用它来存储每个节点的特定属性,例如从数据库返回的 json 对象。在了解这一点之前,我总是在每次单击节点时向服务器发出 ajax 请求。现在,一旦加载了属性,我将它们存储在 Node 对象中,我可以像 nodesManager.requestNode("1").getProperties() 一样访问它们
【解决方案3】:

如果你真的想压缩周期...

(function (nodesManager) {
    var nodes = [];
    nodesManager.requestNode = function(id) {
        // reduce number of checks
        return nodes[id] !== undefined ? nodes[id] : nodes[id] = new Node(id);
    }
} (window.nodesManager = window.nodesManager || {}));

$("#nodesList").delegate("li", "click", function() {
    // no need to wrap this in jQ just to get the id
    var node_Id = this.id.replace("node_", "");

    var newNodeName = "I am a new value";
    nodesManager.requestNode(node_Id).changeName(newNodeName);
});

如果您真的想让这段代码更高效,而不是压缩循环,我们需要更深入地了解它试图实现的目标。

【讨论】:

    猜你喜欢
    • 2016-09-23
    • 1970-01-01
    • 2016-03-14
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    相关资源
    最近更新 更多