jQuery代码组织和性能

nor*_*rth 12 javascript performance jquery design-patterns organization

在对这个主题进行了一些研究之后,我一直在尝试使用模式来组织我的jQuery代码(例如,Rebecca Murphy 在jQuery会议上做过这方面的演示).

昨天我检查了(显示)模块模式.结果看起来有点像我认为的YUI语法:

//global namespace MyNameSpace
if(typeof MNS=="undefined"||!MNS){var MNS={};}

//obfuscate module, just serving as a very simple example
MNS.obfuscate = function(){
    //function to create an email address from obfuscated '@'
    var email = function(){
        $('span.email').each(function(){
            var emailAddress = $(this).html().replace(' [ @ ] ','@');
            $(this).html('<a href="mailto:' + emailAddress + '">' + emailAddress + '</a>');

        });
    };    
    return {
        email: email
    };    
}();

//using the module when the dom's ready
jQuery(document).ready(function($){
    MNS.obfuscate.email();
});
Run Code Online (Sandbox Code Playgroud)

最后我有几个模块.一些自然包括"私有成员",在这种情况下,它意味着变量和/或函数,这些变量和/或函数仅对该模块中的其他函数很重要,因此不会在return语句中结束.

我认为将模块中的部分连接(与搜索有关的所有内容)组合在一个模块中是有意义的,给出了整个结构.

但在写完这篇文章之后,我读了John(Resig)的一篇文章,在那里他还写了关于模块模式的性能:

"使用一堆原型属性实例化一个函数是非常非常快的.它完全破坏了模块模式,类似于水中.因此,如果你有一个经常访问的函数(返回一个对象),你想要的人们要与之交互,那么将对象属性放在原型链中并实例化它对你有利.这里是代码:

// Very fast
function User(){}
    User.prototype = { /* Lots of properties ... */ };

// Very slow
function User(){
    return { /* Lots of properties */ };
}
Run Code Online (Sandbox Code Playgroud)

(约翰提到他并不反对模块模式"本身" - 只是为了让你知道:)

然后我不确定我是否正在使用我的代码进入正确的方向.问题是:我真的不需要任何私人成员,我也认为我暂时不需要继承.我现在想要的只是一个可读/可维护的模式.我想这可归结为个人偏好到一定程度,但我不想最终得到具有(相当严重)性能问题的可读代码.

我不是JavaScript专家,因此在性能测试方面更不是专家.首先,我并不知道John提到的事物("经常访问的函数(返回一个对象)",你希望人们与之交互的东西),很多属性等等都适用于我的代码.我的代码与之交互的文档并不大,有100或1000个元素.所以也许这根本不是问题.

但我想到的一件事是,而不仅仅是

$('span.email').each(function(){
    var emailAddress = $(this).html().replace(' [ @ ] ','@');
    $(this).html('<a href="mailto:' + emailAddress + '">' + emailAddress + '</a>');
});
Run Code Online (Sandbox Code Playgroud)

(在domready函数内),由于使用了模块模式,我创建了两个"额外"函数,混淆和电子邮件.创建附加功能需要花费一些时间.问题是:在我的情况下,它是否可以衡量?

我不确定在上面的例子中是否创建了一个闭包(在jQuery论坛上的一篇有趣的帖子中我读到了以下内容:"如果内部函数没有引用任何内容,那么内部函数是否创建了一个关于它的哲学辩论一个外部函数的变量对象......"),但我确实在我的实际代码中有闭包.即使我不认为我有任何循环引用,我不知道这可能会导致高(呃)内存消耗/垃圾收集问题.

我真的很想听听你的意见,也许会看到你的代码的一些例子.此外,您更喜欢哪些工具获取有关执行时间,内存和CPU使用情况的信息?

bob*_*nce 7

我也认为我暂时不需要继承

确实.这并不适用于将模块用作命名空间.它是关于类实例的类比.

你从一个完全新的做每一个实例创建对象,{name: member}对象是比你创建对象使用效率较低new ClassClass.prototype.name= member.在原型的情况下,member值被共享,从而产生更轻量级的实例.

在您的示例中MNS是单例,因此通过原型共享成员没有任何好处.

我不确定在上面的例子中是否创建了闭包

是的.即使外部函数中没有定义变量,仍然会为外部函数创建一个LexicalEnvironment和scope对象,thisarguments在其中进行绑定.一个聪明的JS引擎可能能够优化它,因为每个内部函数必须隐藏thisarguments使用它们自己的副本,但我不确定任何当前的JS实现实际上是这样做的.

在任何情况下,性能差异都应该是不可检测的,因为您没有在参数中添加任何重要内容.对于一个简单的模块模式,我认为没有任何伤害.

此外,您更喜欢哪些工具获取有关执行时间,内存和CPU使用情况的信息?

开始的地方就是在for循环中执行代码10000次,看看有多大new Date().getTime(),在你可以掌握的多个不同的浏览器上执行了几次.

$(this).html().replace('[@]','@');

(这应该做什么?目前它会将span的HTML读入一个新的String,只替换[ @ ]with 的第一个实例@,并返回一个新String值.它不会改变DOM中的现有内容.)