微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

这可能已经被问了很多次,我已经搜索了SO,但到目前为止,我读到的所有答案都不是我正在寻找的.

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

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

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

var site = {
  version: '0.1',init: function() {
    site.registerEvents();
  },registerEvents: function() {
    $('.back-to-top').on('click',site.scrollToTop);
  },scrollToTop: function() {
    $('body').animate({scrollTop: 0},400);
  }
};

$(function() {
  site.init();
});

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

site.auth = {
  init: function() {
    site.auth.doms.loginButton.on('click',site.auth.events.onLoginButtonClicked);
  },doms: {
    loginButton: $('.login'),registerButton: $('.register')
  },events: {
    onLoginButtonClicked: function() {
    }
  },fbLogin: function() {
  }
};

site.dashboard = {
};

site.quiz = {
};

// more modules

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

var site = (function() {
  function init() {
    $('.back-to-top').on('click',scrollToTop);
    site.auth.init();
  }

  function scrollToTop() {
    $('body').animate({scrollTop: 0},400);
  }

  return {
    init: init
  }
})();

site.auth = (function() {
  var doms = {
    loginButton: $('.login'),registerButton: $('.register')
  };

  function init() {
    doms.loginButton.on('click',onLoginButtonClicked);
  }

  function onLoginButtonClicked() {

  }

  return {
    init: init
  }
})();

// more modules

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

解决方法

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

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

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

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

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

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

您目前使用的方式:

var module = (function () { /* ... */ return {}; }());

module.submodule = (function () { /*...*/ return {}; }());

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

var module = {
    a : "",method : function () {},Meta : { }
};

module.submodule = {
    a : "",Meta : { }
};

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

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

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

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

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

var rectangle = (function (width,height) {
    var public_interface = {
        width  : width,height : height,area   : width * height,perimeter : (2 * width) + (2 * height)
    };
    return public_interface;
}(12,24));

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

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

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

MyApp.myServices.webService.send();

并期待找到:

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

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

原文地址:https://www.jb51.cc/js/151722.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐