14

我正在尝试了解 JavaScript 模块模式。我已经看过它应该是什么样子的例子,但我不明白如何使用它。

例如,这里发生了一些事情:

$('input#share').on("click", function() {

    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
        $("#messageempty").jmNotify();
        $('.remove_loading').remove();
    } else {
        addMessage(message);
    }

    return false;
});


function addMessage(message)
{
    $.ajax({
        url: '/test',
        type: 'POST',
        dataType: "json",
        data: {'message' : message},
        success: function(data) {
                ...
        },
        error: function() {
            ...
        }
    });
}

我怎样才能使用上面的例子:

var myTest = function() {
    var selectId;
    function addMessage () {
        // ...
    }
    return { // public interface
        publicMethod1: function () {
            // all private members are accesible here
        }
    };
};
var start = myTest();

我在哪里添加点击事件,声明我的变量,addMessage使用 ajax 调用添加函数。并调用addMessage函数?我必须把所有东西都包起来$(document).ready(function()吗?

任何人都可以为我阐明这一点吗?

谢谢

4

5 回答 5

22

这是一个相当自以为是的主题,但我会这样做(不完全了解您的完整应用程序及其功能),有点像这样:

var myApp = (function() {

  var someElement = $("#foo"); //some element I know I'll use lots

  var addMessage = function(message) {
    $.ajax({
      url: '/test',
      type: 'POST',
      dataType: "json",
      data: {'message' : message},
      success: function(data) {
              ...
      },
      error: function() {
          ...
      }
    });
  };

  var inputClick = function(event) {
    event.preventDefault();
    //depending on if you'll reuse these selectors throughout the app I might have these as variables
    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
      $("#messageempty").jmNotify();
      $('.remove_loading').remove();
    } else {
      addMessage(message);
    }
  };

  var bindFunctions = function() {
    $("input#share").on("click", inputClick)
  };

  var init = function() {
    bindFunctions();
  };

  return {
    // EDIT: 27/12/16 - need to return init for 'usage' example to work
    init: init,
    addMessage: addMessage
    //anything else you want available
    //through myApp.function()
    //or expose variables here too
  };


})();

//usage

myApp.init();

您的模式的原始代码是错误的,该函数必须()在最后,使其成为立即调用的函数,然后执行,通过return statement.

您可能希望与我所做的略有不同,这只是一个基本的想法,但我希望它可以帮助您入门。

不久前有人问了一个与此模式有关的问题,我回答了它,解释了我们为什么使用该语句(function() {})();以及该return语句在该上下文中如何工作,如果您对此感到有些困惑,那也可能值得一读。

于 2012-08-20T17:47:49.693 回答
13

显示模块模式的使用如下:

var moduleName = (function () {
    var privateVariable = 'private';

    var privateMethod = function () {
        alert('this is private');
    };

    // this is the "revealed" part of the module
    return { 
        publicVariable: 'public',
        publicMethod: function () {
            alert('this is public');
        }
    };
}());

您还可以将公共变量/方法定义为私有变量,然后公开对它们的引用,使它们公开。这是一个偏好问题。

在您的示例中,如果您想addMessage成为模块的一部分,您可以这样做:

var moduleName = (function () {
    // this becomes public due to the reference exposure in the return below
    var addMessage = function () {
        // do whatever
    };

    // this is the "revealed" part of the module
    return { 
        addMessage: addMessage
    };
}());

moduleName.addMessage();
于 2012-08-20T17:42:03.763 回答
1

这个想法是通过将代码分成段/模块来减少外部世界的可见性和更好的代码管理。如果您想了解模块化设计模式的真正良好用法以及我们如何从中受益的某种方式,请查看此它。
http://learn.jquery.com/code-organization/concepts/

于 2013-10-17T02:29:30.760 回答
1

与 JAVA 不同,Javascript 在属性或方法上没有私有和公共的概念。让我们创建一个名为 person 的对象,它有 2 个属性 firstName 和 lastName,并创建 2 个函数,它们将作为我们的属性的 getter。在 Javascript 中,我们可以将函数创建为对象的属性,并且这些函数可以像任何其他属性一样在任何地方访问。

var person={
  "firstName":"Anoop",
  "lastName":"Rai",
  "getFirstName":function(){
    return this.firstName;
  },
  "getLastName":function(){
    return this.lastName;
  }
};
console.log(person.getFirstName());
console.log(person.firstName);

正如预期的那样,上面的代码 11 打印出 Anoop 和 Anoop。嗯,这对面向对象的编程不好。好吧,我们成功地实现了 getter,所以我们还应该有应该是公共范围的 setter,并且属性应该标记为私有范围(什么???这些私有和公共概念属于 JAVA、C++ 之类的语言)。我们的意图是好的,让我们应用特定于 Javascript 的概念。我们不想做 person.firstName,我们想要直接阻止对属性的访问。在像 JAVA 这样的语言中,由于私有和公共,我们实现了对属性的受控访问,但在 Javascript 中,一切都是公共的。

Javascript 使用闭包的概念来实现私有和公共之类的东西。这种模式称为模块模式。也就是说,对公共访问隐藏变量。为了实现作用域,请将您的代码包装在一个函数中(请记住,作用域是通过 Javascript 中的函数实现的)。

function createPerson(){
  var returnObj={
    "firstName":"Anoop",
    "lastName":"Rai",
    "getFirstName":function(){
      return this.firstName;
    },
    "getLastName":function(){
      return this.lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

现在也在上面的行打印 Anoop 和 Anoop。仍然没有成功。只要属性与对象绑定,就可以直接访问它。让我们解开它。我们创建函数范围的变量(闭包变量)而不是属性。

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

Now above lines prints Anoop and undefined. How does this happen? Because of closures, when the functions getFirstName and getLastName was created the functions had the whole scope chain or say pointers to the relevant variables i.e. firstName and lastName. The object returnObj does not remember the variabes but the function objects remembers, because of closures. Looks like we achieved what we wanted to, but one thing is left and that is setters for the controlled access of firstName and lastName. Let’s implement setters.

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    },
    "setFirstName":function(name){
      return firstName=name;
    },
    "setLastName":function(name){
      return lastName=name;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
person.setFirstName("Kumar");
console.log(person.getFirstName());

We successfully modified firstName but in a controlled manner.

http://jkoder.com/the-module-pattern-javascript-way-of-hiding-data-in-objects-from-public-access/

于 2016-09-01T11:35:04.323 回答
0

我对 Mootools 有一些经验,但我是 jQuery 新手。我已经阅读了文档,看起来组织代码最聪明的方法是模块模式,所以我正在尝试。然而,这种风格似乎缺少的一件事是任何“自我”的概念,因为 IIFE 中的每个变量都是一个自包含的对象(不是双关语)。

所以......也许这违背了整个目的,但你能做这样的事情,并且仍然让它在模块模式样式有效的所有方面都是“有效的”吗?

var feature = ( function () {

    var self = {

        config: {
            option1: 'thing 1',
            option2: 'thing 2'
        },


        init: function (options) {

            // allow overriding the default config
            jQuery.extend( self.config, options );

            self.doSomething();

        },

        doSomething: function () {

        },

    };

    return {
        init: self.init
    }

})();

我喜欢这个的是我可以使用“self”在内部引用所有的方法和属性。我仍然能够使用“return”对象公开我想要的方法,所以(我猜)没关系。但我是个新手,这看起来很简单(乍一看)很优雅,我一定错过了一个主要问题。它与我从 Mootools 熟悉的 Object Literal 格式共享编码风格。所以也许我正在尝试将一个圆形钉子安装到一个方孔中。也许内部对象文字不是必需的,因为我可以说“doSomething”而不是“self.doSomething()”?是这样吗?

部分我喜欢这个,因为我可以将 $.ajax 的“context”参数设置为“self”,这似乎是一个胜利。

于 2013-08-08T20:03:53.187 回答