设为首页 加入收藏

TOP

AngularJS —— 使用模块组织你的代码(一)
2014-11-23 21:36:28 来源: 作者: 【 】 浏览:37
Tags:AngularJS 使用 模块 组织 代码

下载 modulePattern.zip - 所有的 4 个 HTML 文件 以及 panacea.js - 1.6 KB


------------------------------------------分割线------------------------------------------


具体下载目录在 /2014年资料/8月/8日/AngularJS —— 使用模块组织你的代码


------------------------------------------分割线------------------------------------------


AngularJS 的库里面有很多东西,但本文中我只想专注于小的,针对特定主题的库,我相信通过它们能对Angular有一个较好的介绍. 理解这篇文章并不需要你有任何Angular相关的,甚至是java script的经验。希望你能从本文中看到一些使用Angular的好处,并乐于动手尝试。


我使用Angular有一段时间了,而在学习Angular的时候,我也喜欢构建一些样例,所以当我一开始深入进去的时候,对于模块或者java script的设计模式,我也没有多想,那样对保持代码组织和条理性有帮助. 那就是所有的重点:保持代码的组织和条理性. 因此,现在我回过头来,创建了这个极其小巧的样例,以展示使用模块可以有多简单. 一路走来,我希望它能够成为一篇好的对Angular的介绍.


大多数时候人们都会尝试去在读者知道模式是啥概念之前就开始阐述一个模式,而这基本上误导了每一个人. 这里要努力使得本文尽量简单,让我们首先来看一看这个问题吧。哪个问题呢?就是有关默认会在全局内存空间被创建的所有东西的java script的问题.


下面就是我所说的意思.


设想你的HTML中有下面这样一段脚本.


范围


你清楚这个变量的范围么
是的,它是全局的。这个布尔值实际上被添加到了浏览器的全局窗口对象中.


这里你可以看到它在Action中是怎样的.


这可能会造成一些名字冲突,也会导致一些严重的bug. 这也许对你而言有点杞人忧天了,是不 但是请设想你是决定要去实现某一个新的JS库,它每分每秒都可以被创建出来. 假设你发现了这个叫做 Panacea.js 的很棒的库,它将解决你所有的问题.


因此你向下面这样在你的页面中引用了它:


如此简单,你就已经解决之前你遇到的所有问题. 然而,因为它是一个庞大的库,而你只想要解决方法,却不回去深挖这个庞大(几千行代码)源文件里的每一行代码. 而深埋在 Panacea.js 里面某个角落的确实下面这样的代码:


这代码真是酷,你知道吗


每个3秒,它都会将这个布尔值设置成相对的值。啊!


如果你想要自己动手验证下这个东西,你可以做下面这几步:


那这是不是很棒呢


带你走近AngularJS系列


我需要为此做出解释,为了要向你展示为什么 java script 的模块模式是很有用的. 我得想你展示 java script 的模块模式,那样我就可以告诉你它是如何在AngularJS中被使用或实现的了.


如此,实际就是,模块模式基本上就是封装了. 封装听起来很熟悉,如果你有点面向对象编程经历的话 -- 而我也希望你能有点这个经验. 封装是面向对象编程的三原则之一。封装的另外一个说法就是数据隐藏。在经典的面向对象编程中——它不同于java script所依赖的原型化OOP -- 数据隐藏是构建一个类模板的内在组成部分.


例如在 C#中, Animal 类的封装 -- 隐藏数据 -- 特定的值被关联到Animal对象. 那样,如果某人决定变更那些值,他或他必须明确的通过初始化一个Animal对象并设置这个对象的值来达到目的. 在java script中,我们则可以随意的在全局窗口对象中设置值.


在java script中,模块已经被创建用来模拟这种封装行为了,如此我们就不会去将我们的变量组织到一个全局的命名空间中,并造成了隐藏很深的难以被发现和修复的问题.


现在你知道为什么了,让我们来看看如何会是这样的.


看上去就好像每次我们向前推进一步,我们都要走点旁门左道. 因为要获得能让我们创建模块模式的java script语法,我们就得去了解一种叫做函数被立即调用的表达式语法,也叫做IIFE ( IIFE 发音是 "iffy").


最基础的 IIFE 看起来像这样:


如果你从来没有看到过像这样的东西,那你就有点说不过去了.


首先,这个名称的第一部分叫做立即被调用的原因是,一般包含这个特殊函数的源文件被加载好了,那么包含在这个函数中的代码就会运行.


你可以看到这个语法的最中心是一个函数。看一下这个代码块,我已经将代码分段并将一些行标上了号,如此我们就可以探讨它了.


首先,看看上面脚本的第2行。这一行通常看来就是一个匿名(也就是没有命名)的函数声明. 而后,第3一直到第4则是这个函数的主题部分。最后,第4行最后以一对括弧结束,这对 括弧会告诉java script解释器去调用这个函数。最终, 所有这些都会被包在一个不归属任何部分的括弧(第1和第5行)中, 而这对括弧会告诉解释器要调用这个外部的匿名函数,它包含了我们所定义的函数.


IIFE 可以带上参数


这段奇怪的语法会在带上参数之后,看起来会更加的奇怪. 它看起来会像是下面这样


现在,你可以看到这个函数可以带上两个会被内部的函数引用的thing1, thing2参数. 被传入值,在示例中是 "in string" 和 382.


现在我们理解了IIFE语法,让我们来创建另外一个代码示例,我们将运行这段代码来看看封装是如何运作的.


为了看看是怎么运行的,你可以做下面这几步:



当方法被调用时 -- 这会在代码被java script解释器加载支护立即发生 -- 而后函数会创建 isDoingWork 变量,并调用console.log()来在控制台输出这个变量的值.


现在,让我们使用开发工具中的控制台来试试我们之前所尝试过的步骤:


当你这样做了之后,你将会看到 浏览器不再相信isDoingWork这个值被定义过。即使是你尝试从全局窗口对象中获取这个值, 浏览器也不认为 isDoingWork 这个值在此对象中被定义了. 你所看到的错误消息看起来会像接下来这张图片中所展示的这样.



函数是一个对象:它创建了范围


这是因为现在你已经把isDoingWork这个变量创建在了一个函数里面 -- 也就是我们们的匿名 IIFE 中 -- 而如此这个变量就只能通过这个函数才能访问到. 有趣的是java script中的所有函数都是第一类对象. 那很简明的意味着函数是一个对象,它可能通过一个变量被访问到. 或者说,另外一种描述的方式是你存储了指向 函数的一个引用,并在稍后的某个时间获取其变量.


在我们第一个示例中,我们的问题是并没有保存一个指向我们匿名函数的引用,所以我们永远也不能再获取到isDoingWork这个值。这就是我们下一个示例要改进的地方.


因为每一个函数都是一个对象,所以每个函数都会有一个this变量,这个变量向开发者提供了指向当前对象的引用. 为了提供在从外部大我们的函数及其范围的访问,我们可以返回这个this变量 -- 而它将会提供一个指向当前对象的引用.


然后,除非我们将这个私有的isDoingWork变量添加到函数引用(this)上,我们也不能够引用这个变量。为此我们要对之前的示例做一下轻微的改动。它看起来会像下面这样:


你可以看到第一行我们加入了一个新的全局变量thing,它包含了

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇VS2008下直接安装使用Boost库1.46.. 下一篇GCC学习笔记

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: