Javascript 模块模式可以用于单例以及多次实例化的对象吗?

发布于 2024-09-10 12:48:08 字数 1555 浏览 8 评论 0原文

我有一页包含两种类型的表单。我在顶部有一个单一的 A 型形式,然后在其下方有 1 个或多个 B 型形式。

我使用模块模式 + jQuery 连接表单上的所有事件、处理验证、ajax 调用等。

这是定义单例(如表单 A 中)和可重用对象类(如表格B?它们非常相似,我不确定是否需要使用对象的 prototype 属性、new 或不同的模式。一切似乎都对我有用,但我担心我错过了一些关键错误。

Form A javascript 看起来像这样:

var MyProject.FormA = (function() {
  var $_userEntry;
  var $_domElementId;

  var validate = function() { 
    if($_userEntry == 0) {
      alert('Cannot enter 0!');
    } 
  }
  var processUserInput = function() {
    $_userEntry = jQuery('inputfield', $_domElementId).val();
    validate();
  }
  return {
    initialize: function(domElementId) {
      $_domElementId = domElementId;
      jQuery($_domElementId).click(function() {
        processUserInput();
      }
    }
  }

})();
jQuery(document).ready(function() {
  MyProject.FormA.initialize('#form-a');
});

Form B 被初始化一次或多次,定义如下:

var MyProject.FormB = function() {
  var $_userEntry;
  var $_domElement;

  var validate = function() { 
    if($_userEntry == 0) {
      alert('Cannot enter 0!');
    } 
  }
  var processUserInput = function() {
    $_userEntry = jQuery('inputfield', $_domElement).val();
    validate();
  }
  return {
    initialize: function(domElement) {
      $_domElement = domElement;
      jQuery($_domElement).click(function() {
        processUserInput();
      }
    }
  }

};
jQuery(document).ready(function() {
  jQuery(".form-b").each(function() {
    MyProject.FormB().initialize(this);
  });
});

I have one page with two types of forms. I have a single form of type A at the top, and then I have 1 or more forms of type B below it.

I use the Module pattern + jQuery to wire up all the events on my forms, handle validation, ajax calls, etc.

Is this the preferred/valid way to define a singleton, as in Form A, and a reusable object class, as in Form B? They are very similar and I'm not sure if I need to be using object the prototype property, new, or a different pattern. Everything seems to work for me but I'm afraid I'm missing some key error.

Form A javascript looks like this:

var MyProject.FormA = (function() {
  var $_userEntry;
  var $_domElementId;

  var validate = function() { 
    if($_userEntry == 0) {
      alert('Cannot enter 0!');
    } 
  }
  var processUserInput = function() {
    $_userEntry = jQuery('inputfield', $_domElementId).val();
    validate();
  }
  return {
    initialize: function(domElementId) {
      $_domElementId = domElementId;
      jQuery($_domElementId).click(function() {
        processUserInput();
      }
    }
  }

})();
jQuery(document).ready(function() {
  MyProject.FormA.initialize('#form-a');
});

Form B, which is initialized one or many times, is defined like so:

var MyProject.FormB = function() {
  var $_userEntry;
  var $_domElement;

  var validate = function() { 
    if($_userEntry == 0) {
      alert('Cannot enter 0!');
    } 
  }
  var processUserInput = function() {
    $_userEntry = jQuery('inputfield', $_domElement).val();
    validate();
  }
  return {
    initialize: function(domElement) {
      $_domElement = domElement;
      jQuery($_domElement).click(function() {
        processUserInput();
      }
    }
  }

};
jQuery(document).ready(function() {
  jQuery(".form-b").each(function() {
    MyProject.FormB().initialize(this);
  });
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小耗子 2024-09-17 12:48:08

您的两个模块都显式返回对象,从而排除了 new 的使用。

原型继承与使用此模式隐藏您的成就的方法并不真正兼容。当然,您可以使用原型表单对象来重写它,并在其上定义验证方法,但是这样该方法将是可见的,并且您将失去封装。

这取决于你是否想要原型的低内存占用和快速对象初始化(共享方法仅存在一次,实例化在恒定时间内运行)或模块模式的封装,这会带来轻微的性能损失(多个定义的相同方法,对象实例化速度变慢,因为每次都必须创建每个方法)

在这种情况下,我建议性能差异微不足道,因此请选择您喜欢的任何内容。就我个人而言,我会说它们之间有太多重复,我倾向于将它们统一起来。你真的需要A成为单身吗?它被意外实例化两次有什么危险?看来这可能是针对这个问题的过度设计。如果你真的必须有一个单例,我会像这样包装非单例(B)类:

var getSingleton = function() {
    var form = MyProject.FormB();
    form.initialize("#form-a");
    console.log("This is the original function");
    getSingleton = function() {     
        console.log("this is the replacement function");
        return form;
    }
    return form;
}

Both of your modules explicitly return objects which precludes the use of new.

Prototype inheritance isn't really compatible with the method hiding your achieving with this pattern. Sure you could re-write this with a prototype form object with your validate method defined on it, but then this method would be visible and you'd loose the encapsulation.

It's up to you whether you want the low memory footprint and speedy object initialization of prototypes (Shared methods exist only once, Instantiation runs in constant time) or the encapsulation of the module pattern which comes with a slight performance penalty (Multiple defined identical methods, Object instantiation slowed as every method has to be created every time)

In this case I would suggest that the performance difference is insignificant, so pick whatever you like. Personally I would say there is too much duplication between them and I would be inclined to unify them. Do you really need A to be a singleton? What are the dangers of it being accidentally instantiated twice? Seems like this is maybe over-engineering for this problem. If you really must have a singleton I'd wrap the non-singleton (B) class like this:

var getSingleton = function() {
    var form = MyProject.FormB();
    form.initialize("#form-a");
    console.log("This is the original function");
    getSingleton = function() {     
        console.log("this is the replacement function");
        return form;
    }
    return form;
}
转身以后 2024-09-17 12:48:08

我认为您只需要编写一种 jQ 插件:

(function($) {
    $.fn.formValidator = function() {
        return $(this).each(function() {
            var $_domElement = $(this);
            $_domElement.click(function() {
                if($('inputfield', $_domElement).val() == 0) {
                    alert('Cannot enter 0!');
                }
            });
        });
    };
})(jQuery);

在这种情况下,您将扩展 jQ 元素方法模块,并且能够将其用于页面上任意数量的元素(对于单个或多个元素集合)。它也将是可链接的。

用法:

$('#form-a').formValidator();
$('.form-b').formValidator();

或者

$('#form-a, .form-b').formValidator();

当然你可以使用一个模块来存储这个函数:

ProjectModule.formValidator = function(selector) {
    return $(selector).each(function() {
        var $_domElement = $(this);
        $_domElement.click(function() {
            if ($('inputfield', $_domElement).val() == 0) {
                alert('Cannot enter 0!');
            }
        });
    });
};

用法:

ProjectModule.formValidator('#form-a, .form-b');

I think you just need to write a kind of jQ plugin:

(function($) {
    $.fn.formValidator = function() {
        return $(this).each(function() {
            var $_domElement = $(this);
            $_domElement.click(function() {
                if($('inputfield', $_domElement).val() == 0) {
                    alert('Cannot enter 0!');
                }
            });
        });
    };
})(jQuery);

In this case you'll extend jQ element methods module and will be able to use it for any amount of elements at the page (for single or multiple elements collection). Also it will be chainable.

Usage:

$('#form-a').formValidator();
$('.form-b').formValidator();

Or

$('#form-a, .form-b').formValidator();

Ofcourse you can use a module to store this function:

ProjectModule.formValidator = function(selector) {
    return $(selector).each(function() {
        var $_domElement = $(this);
        $_domElement.click(function() {
            if ($('inputfield', $_domElement).val() == 0) {
                alert('Cannot enter 0!');
            }
        });
    });
};

Usage:

ProjectModule.formValidator('#form-a, .form-b');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文