jQuery官方文档:  http://learn.jquery.com/code-organization/concepts/

Code Organization Concepts(代码组织概念)

当你不再只是用jQuery为你的网站增添一些简单的功能,转向做一些成熟的客户端应用,那你就需要考虑如何组织你的代码。这章,我们将简要地介绍jQuery应用中几种常用的代码组织模式,探究RequireJS依赖管理以及构建系统。

When you move beyond adding simple enhancements to your website with jQuery and start developing full-blown(成熟的) client-side applications, you need to consider how to organize your code. In this chapter, we'll take a look at various code organization patterns you can use in your jQuery application and explore the RequireJSdependency management and build system.

Key Concepts(关键概念)

在开始学习代码组织模式之前,理解一些通用的优良的代码组织模式是非常重要的。

Before we jump into code organization patterns, it's important to understand some concepts that are common to all good code organization patterns.

代码应该按照功能为单位划分,例如:模块、服务等等。不要把所有的代码都堆在一个大大的$( document ).ready()的块中。这种观点,不严谨地说,可以叫做“封装”。

  • Your code should be divided into units of functionality — modules, services, etc. Avoid the temptation to have all of your code in one huge $( document ).ready() block. This concept, loosely, is known as encapsulation.

不要重复copy代码,找出函数中相似功能的代码片段,利用继承技术避免重复代码。

  • Don't repeat yourself. Identify similarities among pieces of functionality, and use inheritance techniques to avoid repetitive code.

尽管jQuery原本就是以DOM操作为中心的,但是JavaScript应用不限于DOM。请记住不是所有的函数都需要或者都应该有一个DOM呈现。

  • Despite jQuery's DOM-centric nature, JavaScript applications are not all about the DOM. Remember that not all pieces of functionality need to — or should — have a DOM representation.

函数单元之间应该是松耦合的,即一个函数单元的执行应该只依赖于它本身,函数单元之间的通信应该通过类似用户事件或发布/订阅的消息系统处理。尽可能避免函数单元之间直接通信。松耦合概念对于首次尝试开发复杂应用的开发者来说,尤其难以拿捏,所以在开始开发后需要特别留心松偶尔原则。

  • Units of functionality should be loosely coupled, that is, a unit of functionality should be able to exist on its own, and communication between units should be handled via a messaging system such as custom events or pub/sub. Stay away from direct communication between units of functionality whenever possible.

The concept of loose coupling can be especially troublesome to developers making their first foray into complex applications, so be mindful of this as you're getting started.

Encapsulation 封装

组织代码第一步就是,把应用的代码段拆分成很多不同块,有时,仅仅这样做就够了。

The first step to code organization is separating pieces of your application into distinct pieces; sometimes, even just this effort is sufficient to lend

The Object Literal  对象字面量

对象字面量也许是封装相关代码最简单的方法。虽然它没有提供任何属性或方法的访问权限控制,但是对于消除匿名函数、以配置项为中心、代码复用和重构是非常有用的。

An object literal is perhaps the simplest way to encapsulate related code. It doesn't offer any privacy for properties or methods, but it's useful for eliminating anonymous functions from your code, centralizing configuration options, and easing the path to reuse and refactoring.

 var myFeature = {
myProperty:"Hello", myMethod:function(){
console.log(myFeature.myProperty); //console.log(this.myProperty) 一样?
},
init:function(settings){
myFeature.settings = settings;
},
myReadSetting:function(){
console.log(myFeature.settings);
} }; myFeature.myProperty === "Hello";//true
myFeature.myMethod(); // myFeature.myMethod是函数,加了小括号才是调用该函数
myFeature.init({foo:"bar"});
myFeature.myReadSetting();

所有属性和方法都是public的,所以属性和方法可以在应用任意位置调用。有一个init方法,然而无需其他,在对象   之前就可以调用它。

The object literal above is simply an object assigned to a variable. The object has one property and several methods. All of the properties and methods are public, so any part of your application can see the properties and call methods on the object. While there is an init method, there's nothing requiring that it be called before the object is functional.

在jQuery代码中如何运用这种模式呢?比方说我们用传统的jQuery风格写了如下代码:

How would we apply this pattern to jQuery code? Let's say that we had this code written in the traditional jQuery style:

//点击列表中某项,通过该项的id加载一些内容,并隐藏兄弟项的内容。
// Clicking on a list item loads some content using the
// list item's ID, and hides content in sibling list items
$( document ).ready(function() {
$( "#myFeature li" ).append( "<div>" ).click(function() {
var item = $( this );
var div = item.find( "div" );
div.load( "foo.php?item=" + item.attr( "id" ), function() {
div.show();
item.siblings().find( "div" ).hide();
});
});
});

如果这只是我们应用中的代码,这样做是可以的。然而,如果它是一个大型应用中的一段代码,我们最好拆分不相干的功能。我们也许会把URL挪到代码外部做成配置文件,最后,为了后续更加容易修改功能块,我们将拆解jQuery调用链。

If this were the extent of our application, leaving it as-is would be fine. On the other hand, if this was a piece of a larger application, we'd do well to keep this functionality separate from unrelated functionality. We might also want to move the URL out of the code and into a configuration area. Finally, we might want to break up the chain to make it easier to modify pieces of the functionality later.

// Using an object literal for a jQuery feature
var myFeature = {
init: function( settings ) {
myFeature.config = {
items: $( "#myFeature li" ),
container: $( "<div class='container'></div>" ),
urlBase: "/foo.php?item="
}; // Allow overriding the default config
$.extend( myFeature.config, settings ); myFeature.setup();
}, setup: function() {
myFeature.config.items
.each( myFeature.createContainer )
.click( myFeature.showItem );
}, createContainer: function() {
var item = $( this );
var container = myFeature.config.container
.clone()
.appendTo( item );
item.data( "container", container );
}, buildUrl: function() {
return myFeature.config.urlBase + myFeature.currentItem.attr( "id" );
}, showItem: function() {
myFeature.currentItem = $( this );
myFeature.getContent( myFeature.showContent );
}, getContent: function( callback ) {
var url = myFeature.buildUrl();
myFeature.currentItem.data( "container" ).load( url, callback );
}, showContent: function() {
myFeature.currentItem.data( "container" ).show();
myFeature.hideContent();
}, hideContent: function() {
myFeature.currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
}
}; $( document ).ready( myFeature.init );

你最先注意到的是这个方法比原来的大多了,其次,如果在我们自己应用中使用这些代码,对象直接量看上去有点过分复杂。假设它不是我们应用中的实现,我们会获得以下几点:

The first thing you'll notice is that this approach is obviously far longer than the original — again, if this were the extent of our application, using an object literal would likely be overkill. Assuming it's not the extent of our application, though, we've gained several things:

我们把feature分解成小的方法,将来如果我们想要修改content如何显示,我们可以很清晰地知道在哪里修改它。在原先的代码中,难于找到修改位置。

  • We've broken our feature up into tiny methods. In the future, if we want to change how content is shown, it's clear where to change it. In the original code, this step is much harder to locate.

我们消除了匿名方法的使用

  • We've eliminated the use of anonymous functions.

我们将配置项移到代码体外,把他们放到了中心的位置。

  • We've moved configuration options out of the body of the code and put them in a central location.

我们消除了链式调用的约束,使得代码更容易重构、混合、重新组织。

  • We've eliminated the constraints of the chain, making the code easier to refactor, remix, and rearrange.

比较重要的特性,对象直接量相对把一段很长的代码写在$(document).ready()块中,是一个明显的提升,因为它让我们得以思考我们的各个功能块。然而,比起简单地把一堆函数声明在一个$(document).ready()块中也没有好太多。

For non-trivial features, object literals are a clear improvement over a long stretch of code stuffed in a $( document ).ready()block, as they get us thinking about the pieces of our functionality. However, they aren't a whole lot more advanced than simply having a bunch of function declarations inside of that $( document ).ready() block.

The Module Pattern(模块化)

模块化克服了对象字面量的限制,提供了变量和函数的私用权限控制。

The module pattern overcomes some of the limitations of the object literal, offering privacy for variables and functions while exposing a public API if desired.

// The module pattern
var feature = (function() { // Private variables and functions
var privateThing = "secret";
var publicThing = "not secret"; var changePrivateThing = function() {
privateThing = "super secret";
}; var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
}; // Public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})(); feature.publicThing; // "not secret" // Logs "secret" and changes the value of privateThing
feature.sayPrivateThing();

在上面的例子中,我们立即执行一个匿名函数并返回一个对象,在函数中,我们定义了一些变量。因为变量定义在函数中,我们从外部没有权限访问函数内部的变量,除非我们把他们放在return的对象中。这意味着,函数外部代码无法访问privateThing变量和changePrivateThing函数。然而sayPrivateThing有权限访问privateThing和changePrivateThing,因为它们都定义在和sayPrivateThing相同的作用域中。

In the example above, we self-execute an anonymous function that returns an object. Inside of the function, we define some variables. Because the variables are defined inside of the function, we don't have access to them outside of the function unless we put them in the return object. This means that no code outside of the function has access to the privateThing variable or to the changePrivateThing function. However, sayPrivateThing does have access to privateThing and changePrivateThing, because both were defined in the same scope as sayPrivateThing.

这种模式是非常强大的,因为你能从变量名中推测,它可以提供你私有变量和函数,当访问受限的API接口,返回的对象的属性和方法。

This pattern is powerful because, as you can gather from the variable names, it can give you private variables and functions while exposing a limited API consisting of the returned object's properties and methods.

下面是之前例子的修改版,展示了如何在只暴露了一个公共方法的模块的情况下,创建相同的feature用模块化模式

Below is a revised version of the previous example, showing how we could create the same feature using the module pattern while only exposing one public method of the module, showItemByIndex().

// Using the module pattern for a jQuery feature
$( document ).ready(function() {
var feature = (function() {
var items = $( "#myFeature li" );
var container = $( "<div class='container'></div>" );
var currentItem = null;
var urlBase = "/foo.php?item="; var createContainer = function() {
var item = $( this );
var _container = container.clone().appendTo( item );
item.data( "container", _container );
}; var buildUrl = function() {
return urlBase + currentItem.attr( "id" );
}; var showItem = function() {
currentItem = $( this );
getContent( showContent );
}; var showItemByIndex = function( idx ) {
$.proxy( showItem, items.get( idx ) );
}; var getContent = function( callback ) {
currentItem.data( "container" ).load( buildUrl(), callback );
}; var showContent = function() {
currentItem.data( "container" ).show();
hideContent();
}; var hideContent = function() {
currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
}; items.each( createContainer ).click( showItem ); return {
showItemByIndex: showItemByIndex
};
})(); feature.showItemByIndex( 0 );
});
 

jQuery学习--Code Organization Concepts的更多相关文章

  1. 很不错的jQuery学习资料和实例

    这些都是学习Jquery很不错的资料,整理了一下,分享给大家. 希望能对大家的学习有帮助. 帕兰 Noupe带来的51个最佳jQuery教程和实例, 向大家介绍了jQuery的一些基本概念和使用的相关 ...

  2. jquery学习笔记(三):事件和应用

    内容来自[汇智网]jquery学习课程 3.1 页面加载事件 在jQuery中页面加载事件是ready().ready()事件类似于就JavaScript中的onLoad()事件,但前者只要页面的DO ...

  3. jQuery学习之路(1)-选择器

    ▓▓▓▓▓▓ 大致介绍 终于开始了我的jQuery学习之路!感觉不能再拖了,要边学习原生JavaScript边学习jQuery jQuery是什么? jQuery是一个快速.简洁的JavaScript ...

  4. jquery学习(一)

    简单的jquery学习,首先在页面引入jquery <!-- 引入jquery --> <script src="js/jquery-1.8.3.js" type ...

  5. jQuery学习笔记(一)jQuery选择器

    目录 jQuery选择器的优点 基本选择器 层次选择器 过滤选择器 表单选择器 第一次写博客,希望自己能够长期坚持,以写博客的方式作为总结与复习. 最近一段时间开始学习jQuery,通过写一个jQue ...

  6. jQuery 学习笔记

    jQuery 学习笔记   一.jQuery概述    宗旨: Write Less, Do More.    基础知识:        1.符号$代替document.getElementById( ...

  7. jQuery学习笔记(一):入门

      jQuery学习笔记(一):入门 一.JQuery是什么 JQuery是什么?始终是萦绕在我心中的一个问题: 借鉴网上同学们的总结,可以从以下几个方面观察. 不使用JQuery时获取DOM文本的操 ...

  8. jQuery学习笔记 - 基础知识扫盲入门篇

    jQuery学习笔记 - 基础知识扫盲入门篇 2013-06-16 18:42 by 全新时代, 11 阅读, 0 评论, 收藏, 编辑 1.为什么要使用jQuery? 提供了强大的功能函数解决浏览器 ...

  9. jquery学习以及下载链接

    jquery学习链接 http://www.w3school.com.cn/jquery/jquery_intro.asp jquery 脚本库下载链接 http://jquery.com/downl ...

随机推荐

  1. 猿题库从 Objective-C 到 Swift 的迁移

    猿题库从 Objective-C 到 Swift 的迁移 引言 相信没有人会怀疑,Swift 是 iOS 开发未来的主流语言,但是由于 Swift 语言的不断变化以及庞大的迁移成本,真正把项目迁移到 ...

  2. 检查linux的磁盘空间占用

    先初步看看哪个目录占用最大$ df -h 然后细看遍历某目录的占用情况:$ sudo du -a /data  | sort -nr | less(单位是KB)

  3. 阿里云ECS服务器无法上传文件的解决方案

    1.安装软件启动FTP服务 yum install vsftpd # 安装service vsftpd start # 启动服务chkconfig vsftpd on # 开机启动 2.防火墙ipta ...

  4. [转]谈NAND Flash的底层结构和解析

    这里我想以一个纯玩家的角度来谈谈关于NAND Flash的底层结构和解析,可能会有错误的地方,如果有这方面专家强烈欢迎指正. NAND Flash作为一种比较实用的固态硬盘存储介质,有自己的一些物理特 ...

  5. OpenGL着色器入门简介

    说明:本文翻译自LearnOpengl经典教程,OpenGL着色器基础介绍的比较通俗易懂,特总结分享一下! 为什么要使用着色器?我们知道,OpenGL一般使用经典的固定渲染管线来渲染对象,但是随着Op ...

  6. python 解除装饰器,调用原本函数。

    假设fun函数被装饰器装饰了,name调用fun,就不是调用fun本身了,那么如何继续调用本身呢.使用fun_raw = fun.__wrapped__这样使用fun_raw就是调用没被装饰器修饰后的 ...

  7. 获取请求IP

    服务器获取客户端或者网页的请求,获取IP时需要注意,并不是直接 request.getRemoteAddr(); 就可以了,因为一个请求到达服务器之前,一般都会经过一层或者多层代理服务器,比如反向代理 ...

  8. JS 浅谈函数柯里化,不明觉厉

    在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 Christopher ...

  9. 阅历>感悟

    1.强扭的瓜不甜.在招聘的时候,面试官看不上你,你也不用赖着要去,你去能干好工作吗?面试官通常比你更清楚这个是事情.在比如谈恋爱,姑娘有更好的目标,不喜欢你了,决定离开你了,你再怎么挽留都是没意义的, ...

  10. 如何使用Vue-cli搭建和运行vue项目

    此文章  主要参考:https://jingyan.baidu.com/article/5225f26bbb430fe6fa0908ce.html 在vue init webpack my-proje ...