【问题标题】:Creating a jQuery plugin: best practices regarding functions' visibility?创建一个 jQuery 插件:关于函数可见性的最佳实践?
【发布时间】:2010-06-10 13:43:19
【问题描述】:

我正在创建一个 jQuery 插件。到目前为止它工作正常,但我对我做事的方式有疑问:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    MyScope.doSomething(jQuery(this).attr("id"));
  });
};

var MyScope = {

  // The functions contained in MyScope are extremely linked to the logic 
  // of this plugin and it wouldn't make a lot of sense to extract them

  doSomething: function(id){
    // something
    doSomethingElse(23);
    // some more code
    doSomethingElse(55);
  },

  doSomethingElse: function(someInt){
    // some code 
  }
};

我使用 MyScope 来存储我所有的“私有”函数。我不希望用户能够去$("p").doSomething(),但我确实需要使用它们。

我可以移动 myMethod 函数中的所有内容,但它会创建一个 100 行长的函数,人们会因此而讨厌我。

在这种情况下,最佳做法是什么?有没有关于这个的很棒的教程?

【问题讨论】:

  • 请注意,整个 jQuery 库都在一个函数中,这是一种完全合法的作用域方法,当您需要闭包时,请使用闭包:)

标签: javascript jquery jquery-plugins


【解决方案1】:

你可以封装你的函数来做你想做的事,像这样:

jQuery.fn.myMethod = function() {
  return this.each(function(){
    doSomething(jQuery(this).attr("id"));
  });        
  function doSomething(id){
    //do something
  }
  function doSomethingElse(){
    // some code
  }
};

You can view a quick demo here

“我可以移动 myMethod 函数中的所有内容,但它会创建一个 100 行长的函数,人们会因此而讨厌我。” ....为什么?

代码必须在某个地方定义,如果您不希望它可从外部访问,有几种方法,但我不明白为什么有人会不喜欢您这样做。这完全取决于范围和您想要的东西,只要您不多次声明它并且只公开您想要的东西,我看不出有任何问题。

声明它有多种样式,有些效果相同,我给出的选项是其中之一,但是将内容放在myMethod 中是一种非常合理的方法。


为了更完整,here's another alternative

(function($) { 
    function doSomething(id){
      //do something, e.g:  doSomethingElse('bob');
    }
    function doSomethingElse(str){
      //some code
    }
    $.fn.myMethod = function() {
      return this.each(function(){
        doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

another:

(function($) { 
    var me = {
        doSomething: function(id){
         //do something, e.g:  this.doSomethingElse('bob');
        },
        doSomethingElse: function(str){
          //some code
        }
    };
    $.fn.myMethod = function() {
      return this.each(function(){
        me.doSomething(jQuery(this).attr("id"));
      });   
    };
})(jQuery);

相关文章:

【讨论】:

  • @nick:只有一个巨大的功能和 0 代码重用是相当糟糕的恕我直言。特别是因为我在 doSomething() 中的 3 或 4 个不同的地方调用了 doSomethingElse()。
  • @marcgg:你的例子没有表明......如果是这种情况,你应该提供更多关于你的用法的线索,即使 hinting 这些将用于 多个插件将是一个开始。
  • @marcgg:这将有助于获得更好的答案:)...一种插件方法是常态,多种方法不是,所以没有其他提示,人们会假设你是什么做匹配大多数情况。
  • 很容易检查。 var f = function() { function g() {}; return g; }; var g1 = f(), g2 = f(); alert(g1 === g2); 如果尼克是对的,你会期待true,如果我是对的,你会期待false。猜猜它是什么:)
  • @Tim Down:在这种情况下,您将它返回到它所在的闭包之外,所以当然每次都需要一个副本来公开它,我不确定这是一个有效的测试一点也不。明确地说,不是说你错了,只是说测试不是确定它的有效方法。
【解决方案2】:

使用大函数来创建新范围并没有错。以下内容保持doSomethingdoSomethingElse 私有,并避免为myMethod 的每次调用定义新的doSomethingdoSomethingElse 函数,如果将doSomethingdoSomethingElse 放入myMethod 中会发生这种情况的定义。

(function() {
  function doSomething(id) {
    // Something
  }

  function doSomethingElse() {
    // Something else
  }

  jQuery.fn.myMethod = function() {
    return this.each(function(){
      doSomething(this.id);
    });
  };
})();

【讨论】:

  • 抱歉,我不确定您在这里要做什么。你能举例说明如何使用它吗?
  • 重点是 doSomethingdoSomethingElse 只能在封闭函数内部访问,不能在外部访问。该示例是在jQuery.fn.myMethod 的定义中对@9​​87654334@ 的调用。保持 doSomethingdoSomethingElse 函数不被其他代码访问是我认为你想要的,这就是实现的目标。我误解了这个问题吗?
  • @tim:太酷了,谢谢!我不太熟悉这个 (function(){})();语法,有没有关于这将做什么的文档?
  • @marcgg: blog.morrisjohns.com/javascript_closures_for_dummies.html 这个名字没有冒犯的意思,但它是一个很好的闭包学习参考。
  • marcgg:通常称为模块模式。如果你用谷歌搜索,有很多参考资料。这个看起来很合理:adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
【解决方案3】:

我会将所有内容都放在 jQuery.fn.myMethod 函数中,以避免可能的命名空间冲突,并使代码更简洁。此模式还允许您创建无法从 myMethod 函数外部访问的私有方法。

jQuery.fn.myMethod = function(options) {
  // Set up a "that" object, which can be referenced from anywhere inside this function
  var that = {};

  // If the plugin needs optional arguments, you can define them this way
  if (typeof(options) == 'undefined') options = {};
  that.options.option1 = options.option1 || 'default value 1';
  that.options.option2 = options.option2 || 'default value 2';

  that.init = function() {
    // psuedo-constructor method, called from end of function definition
  }

  that.doSomething = function() {
    // something
  }

  that.doSomethingElse = function() {
    // something else
  } 

  // Call init method once all methods are defined
  that.init();

  // Return the matched elements, to allow method chaining
  return jQuery(this);
}

【讨论】:

  • 这很有趣,你知道这是否是一种常见的做法吗?
  • that 的意义何在?您可以使用局部变量而不是具有属性的对象。
  • 我是这么认为的,至少在我和我的同事中是这样。我也看到很多这样写的 jQuery 插件,或者至少是这样的一些变体。
  • “那个”对象的重点是避免可能的命名空间冲突。例如,如果我刚刚调用了我的方法 init()、doSomething() 和 doSomethingElse(),我可能会意外调用同名的全局函数。虽然这不太可能,但它仍然是一件少担心的事情。此外,您可以将“那个”对象传递给回调方法,让它们访问当前范围。
  • @harold1983:有什么例子吗?
猜你喜欢
  • 2013-04-19
  • 2012-05-23
  • 2012-05-26
  • 2012-12-03
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
相关资源
最近更新 更多