对象文字或模块化Javascript设计模式

前端之家收集整理的这篇文章主要介绍了对象文字或模块化Javascript设计模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这可能已经被问了很多次,我已经搜索了SO,但到目前为止,我读到的所有答案都不是我正在寻找的.

我在一个网站上使用适度的DOM元素显示/隐藏,一些AJAX调用,也可能是别的.所以我会有两个主要的脚本文件(HTML5 Boilerplate标准)

  1. plugins.js // third party plugins here
  2. site.js // all my site specific code here

以前我使用对象字面设计模式,所以我的site.js是这样的:

  1. var site = {
  2. version: '0.1',init: function() {
  3. site.registerEvents();
  4. },registerEvents: function() {
  5. $('.back-to-top').on('click',site.scrollToTop);
  6. },scrollToTop: function() {
  7. $('body').animate({scrollTop: 0},400);
  8. }
  9. };
  10.  
  11. $(function() {
  12. site.init();
  13. });

到目前为止这么好,它很好读,所有的方法都是公开的(我有点像这样,我可以通过Chrome开发工具直接测试他们,如果需要).然而,我打算将网站的某些功能分解为更多的模块化样式,所以我想在上面的代码(或单独的文件)中有类似的东西:

  1. site.auth = {
  2. init: function() {
  3. site.auth.doms.loginButton.on('click',site.auth.events.onLoginButtonClicked);
  4. },doms: {
  5. loginButton: $('.login'),registerButton: $('.register')
  6. },events: {
  7. onLoginButtonClicked: function() {
  8. }
  9. },fbLogin: function() {
  10. }
  11. };
  12.  
  13. site.dashboard = {
  14. };
  15.  
  16. site.quiz = {
  17. };
  18.  
  19. // more modules

正如你所看到的,它是非常可读的.但是有一个明显的缺点,我必须编写代码如site.auth.doms.loginButton和site.auth.events.onLoginButtonClicked.突然变得难以阅读,而且功能越来越复杂,时间越长越好.然后我尝试了模块化模式:

  1. var site = (function() {
  2. function init() {
  3. $('.back-to-top').on('click',scrollToTop);
  4. site.auth.init();
  5. }
  6.  
  7. function scrollToTop() {
  8. $('body').animate({scrollTop: 0},400);
  9. }
  10.  
  11. return {
  12. init: init
  13. }
  14. })();
  15.  
  16. site.auth = (function() {
  17. var doms = {
  18. loginButton: $('.login'),registerButton: $('.register')
  19. };
  20.  
  21. function init() {
  22. doms.loginButton.on('click',onLoginButtonClicked);
  23. }
  24.  
  25. function onLoginButtonClicked() {
  26.  
  27. }
  28.  
  29. return {
  30. init: init
  31. }
  32. })();
  33.  
  34. // more modules

正如你所看到的,那些长名字已经不见了,但是我想我必须在site.init()函数中初始化所有其他模块来构造它们?那么我必须记住要返回其他模块需要访问的功能.他们都是可以的,我猜这虽然有点麻烦,但总体来说,我是否使用模块化模式更好的工作流程?

解决方法

正确的答案,这里当然是:“这取决于”.

如果您完全可以使用所有数据和所有方法,对于网站的每个部分都是100%公开的,那么只要使用单个文字(或多个文字),如果需要,嵌套对象就完全可以,假设您可以保持它变成一个巨大的代码球.

如果你想要任何种类的私有状态,它具有任何持久性(即:每次运行一个函数都不会重置),那么显示模块是非常好的.

说:
完全不需要使用.init方法显示模块.
如果您的模块可以自包含,那么只需要专注于导出您想要公开的内容.

为此,当我编写一个团队可能看到的代码时,稍后,我发现自己创建一个public_interface对象并返回它(返回的匿名对象的命名版本).

这样做的好处是很小的,除了增加一些理解,即需要将公开的内容需要附加到接口上.

您目前使用的方式:

  1. var module = (function () { /* ... */ return {}; }());
  2.  
  3. module.submodule = (function () { /*...*/ return {}; }());

没有比文字更好还是更差,因为你可以很容易地做到这一点:

  1. var module = {
  2. a : "",method : function () {},Meta : { }
  3. };
  4.  
  5. module.submodule = {
  6. a : "",Meta : { }
  7. };

直到你打了一些不适合你的东西,用什么来满足你的需求.

就个人而言,我通常会以文字形式构建任何仅数据对象:config-objects,从其他连接进入的对象等

任何污垢简单的对象,需要一个或两个方法,并且可以通过仅嵌套一个或两个深度来构建,我可以逐字地构建(只要不需要初始化).

  1. // ex:
  2. var rectangle = {
  3. width : 12,height : 24,area : 0,perimeter : 0,init_area : function () { this.area = this.width * this.height; return this; },// buh...
  4. init_perimeter : function () { this.perimeter = (this.width * 2) + (this.height * 2); return this; } // double-buh...
  5. }.init_area().init_perimeter();

如果我需要其中的几个,也许我会做一个构造函数.
但是,如果我只需要这样一个独特的东西,就不会像我这样做,而是让我头痛:

  1. var rectangle = (function (width,height) {
  2. var public_interface = {
  3. width : width,height : height,area : width * height,perimeter : (2 * width) + (2 * height)
  4. };
  5. return public_interface;
  6. }(12,24));

如果有更高级的计算需要,我可以保留任何额外的vars私人,并从里面工作.
如果我需要在一个对象内部具有敏感数据,并且可以对该数据进行处理,那么我可以使用调用这些私有函数的公共函数,并返回结果,而不是提供访问.

此外,如果我重构我的代码,并且决定在某个时候重命名矩形,那么嵌套3或更深的任何函数,即指向矩形也必须被修改.
再次,如果你正在构造你的方法,使他们不需要直接询问任何比这更远的对象,那么你不会有这个问题?

…但是如果你有一个界面看起来像:

  1. MyApp.myServices.webService.send();

并期待找到:

  1. MyApp.appData.user.tokens.latest; // where personally,I might leave tokens in a closure

如果您更改了AppData模块的结构,您将在WebService模块中出现各种错误,直到找到对旧格式的所有引用,并重命名它们.

猜你在找的JavaScript相关文章