如何在实际示例中使用 javascript 模块模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12042260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:57:54  来源:igfitidea点击:

how to use the javascript module pattern in a real example?

javascriptjquerydesign-patternsmodule-pattern

提问by Patrioticcow

I am trying to understand the JavaScript Module Pattern. I've seen examples of what it should look like, but I don't understand how to use it.

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

For example, a few things are happening here:

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

$('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() {
            ...
        }
    });
}

How can I use the above example with:

我如何使用上面的例子:

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

Where do I add the click event, declare my vars, add the addMessagefunction with the ajax call. and call the addMessagefunction? Do i have to wrap everything in $(document).ready(function()?

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

Can anyone shed some light on this for me?

任何人都可以为我解释一下吗?

Thanks

谢谢

回答by Hyman Franklin

This is quite an opinionated subject, but I'd do it (without entirely knowing your full app and what it does), somewhat like so:

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

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();

Your original code for the pattern is wrong, the function has to have ()at the very end, to make it a function that is immediately invoked, and then executes, exposing anything through the return statement.

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

You may wish to differ slightly from what I've done, it's only a basic idea but I hope it might get you started.

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

Someone a while back asked a question relating to this pattern and I answered itexplaining why we use (function() {})();and how the returnstatement works in that context, if you're slightly confused by it that might be worth reading too.

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

回答by jbabey

The revealing module pattern is used like this:

揭示模块模式是这样使用的:

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');
        }
    };
}());

You can also define the public variables/methods as privates and then expose a reference to them, making them public. This is a matter of preference.

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

In your example, if you wanted addMessageto be part of the module, you would do it like this:

在您的示例中,如果您想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();

回答by kta

The idea is to cut down the visibility from outside world and better code management by dividing your code into segments/modules.Check this out if you want to see a really good usage of modular design pattern and some way of how we can get benefit from it.
http://learn.jquery.com/code-organization/concepts/

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

回答by Anoop Rai

Unlike JAVA, Javascript does not have the concept of private and public on properties or on methods. Let's create an object called person which has 2 properties firstName and lastName, and also create 2 functions which will be getters for our properties. In Javascript we can create functions as properties of objects & those functions are accessible like any other property anywhere.

与 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);

As expected above codes 11 prints Anoop and Anoop. Hmmm, that's not good for object oriented programming. Well, we successfully implemented getters and so we should also have setters that should be of public scope and properties should be marked as private scope (what??? these private and public concept belongs to JAVA, C++ like languages). Our intentions are good, lets apply concepts specific to Javascript. We don't want to do person.firstName, we want the prevent the access of the property directly. In languages like JAVA because of private and public we achieved the controlled acccess of properties, but in Javascript everything is public.

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

Javascript uses concept of closures to implement things like private & public. This pattern is called Module Pattern. That is, hiding variables from public access. In order to implement scopes, wrap your codes in a function (remember, scopes are implemented via functions in 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);

Now also above lines prints Anoop and Anoop. Still no success. As long as properties are tied to the object it will be accessed directly. Let's untie it. Instead of properties we make variables of function scope (closure variables).

现在也在上面的行打印 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.

现在上面的行打印 Anoop 和 undefined。这是怎么发生的?由于闭包,当函数 getFirstName 和 getLastName 被创建时,这些函数具有整个作用域链或者说指向相关变量的指针,即 firstName 和 lastName。由于闭包,对象 returnObj 不会记住变量,但函数对象会记住。看起来我们实现了我们想要的,但还剩下一件事,那就是对 firstName 和 lastName 的受控访问的设置器。让我们实现setter。

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.

我们以可控的方式成功地修改了 firstName。

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

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

回答by hairbo

I've got some experience with Mootools, but I'm a jQuery novice. I've read through the docs, and it looks like the smartest way to organize code is the Module Pattern, so I'm trying that out. However, one thing that seems to be missing from that style is any notion of "self", since each variable within the IIFE is a self-contained object (no pun intended).

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

So...maybe this defeats the whole purpose, but could you do something like this, and still have it be "valid" in all the ways that the module pattern style is valid?

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

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
    }

})();

What I like about this is that I can internally reference all of the methods and properties using "self". I'm still able to expose the methods that I want using the "return" object, so (I guess) that's okay. But I'm such a novice, and this seems so simple and (at first glance) elegant, that I must be missing a major gotcha. It shares the coding style with the Object Literal format, which is what I'm familiar with from Mootools. So maybe I'm trying to fit a round peg into a square hole. Maybe the internal object literal isn't necessary, because rather than "self.doSomething()", I can just say "doSomething"? Is that the case?

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

Partially I like this because I can set the "context" argument of $.ajax to be "self", which seems like a win.

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