【问题标题】:JQuery JavaScript Design: Self Executing Function or Object Literal? [closed]JQuery JavaScript 设计:自执行函数还是对象字面量? [关闭]
【发布时间】:2010-09-16 08:43:09
【问题描述】:

我很好奇在构建封装代码块时是否有任何与 JQuery 相关的最佳实践。

通常,当我构建一个页面时,我喜欢将该页面中使用的函数封装在一个对象中。这允许我在构建应用程序时进行一些封装。没有什么比看到包含一堆这样的 JavaScript 文件更让我讨厌的了

function doSomethingOnlyRelevantOnThisPage() {
    // do some stuff
}

这会导致设计混乱,并不能很好地封装功能。

通常在许多框架中,都有一个标准用于执行这种封装。

在 Mootools 中,他们偏爱 Object Literal Notation:

var Site = {        
    // properties and methods
}

在 YUI 中,他们偏爱自执行函数符号:

(function() { // properties and methods })()

第二个例子的好处是创建了一个闭包,因此允许您定义私有属性和方法。

我的问题是:是否有任何 JQuery 爱好者有任何最佳实践来创建这些干净封装的结构?使用它们的理由是什么?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    由于我使用 jQuery 已经有一段时间了,我决定采用一种适合我的标准模式。

    它是 YUI 模块模式和一些 jQuery 插件模式的结合。。我们最终使用了自执行闭包模式。这在几个方面是有益的:

    1. 它将代码保持在最低限度
    2. 它强制将行为与表示分离
    3. 它提供了一个防止命名冲突的闭包

    这就是它的样子:

    ;(function($) {        
        var myPrivateFunction = function() {
        };
    
        var init = function() {
            myPrivateFunction();
        };
    
        $(init);
    })(jQuery);
    

    我们意识到,与 YUI 模块模式类似,分配函数执行的结果会暴露可能从表示代码中调用的代码。我们想防止这种情况发生,所以这种模式适合。

    当然,我们可以内联编写 init 方法,而无需为函数定义变量。我们一致认为明确定义 init 函数可使代码对读者更清晰。

    如果我们想在页面/外部 js 文件之间共享函数会发生什么?我们只是简单地挂钩到 jQuery 提供的用于扩展 jQuery 对象本身的现有机制 - 扩展函数。

    如果函数是静态的,我们使用 $.extend,如果它们对包装集进行操作,我们使用 $.fn.extend 函数。

    希望这对某人有所帮助。

    【讨论】:

    • 我一直看到这种模式,但我渴望一个更完整的示例 - 我有一个页面,其中包含一些不同且相当复杂的交互元素,它们的逻辑应该彼此分开封装。在这种情况下组织代码有什么建议吗?对每个不同的 UI 部分使用 $.fn.extend 似乎违反直觉。
    • 我绝对不提倡使用扩展 jquery 函数,除非你正在编写一个插件——所以它可以在许多页面中重复使用。在您的情况下,我会将我的功能分解为不同的部分,创建一个自执行函数以在其自己的闭包中包含该逻辑。然后可以通过 $.extend 将任何共享代码附加到 jQuery 本身,这将允许您拥有不需要元素上下文即可运行的辅助函数。
    • 关于立即调用函数表达式(IIFE)的非常好的文章benalman.com/news/2010/11/…
    【解决方案2】:

    我在开发时使用 YUI 和 jQuery(YUI 小部件和一些便利功能,jQuery 选择器和 javascript“扩展”),我使用的通用 javascript 模板是这样的:

    /*global YAHOO, $ */
    
    // Create the public-scope accessable namespace for this page
    YAHOO.namespace('Project');
    
    YAHOO.Project.page = function() {
        // Private members
    
        var self = {};
    
        // Public members
        var pub = {};
    
        pub.init = function() {
    
        };
    
        return pub;
    } ();
    
    // When the DOM is loaded, initialize this module
    $(document).ready(YAHOO.Project.page.init);
    

    现在很明显,如果您不想使用 YUI,可以删除 YAHOO.namespace() 调用,但这是基本大纲。它使用对象字面量表示法,但也允许您定义私有属性和方法。

    请记住,在调用私有成员或引用私有变量时将它们引用为self.funcName()。您可以在 self 对象之外定义它们,但是在您的对象中到处都会出现错误,您试图确定 size_of() 是私有方法还是在其他地方全局定义。

    【讨论】:

      【解决方案3】:

      我通常遵循原型模式:

      MyFunction = function(param1, param2)
      {
         this.property1 = param1;
         // etc.
      }
      
      MyFunction.prototype =
      {
          memberOne: function(param1)
          {
             // ...
          },
      
          memberTwo: function(param2)
          {
          }
      }
      

      你会得到一个“构造函数”(函数本身)和封装的“方法”和“字段”。

      对于习惯于基于类的 OO 语言的人来说更容易:)

      【讨论】:

      • 但这仅在您计划将状态封装在对象中时才有用。您必须在这些对象上调用 new 来创建实例。在我的例子中,它们的行为更像是 OO 术语中的静态类。
      • 不错,不错...在这种情况下,我更喜欢自执行匿名函数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      相关资源
      最近更新 更多