编程模式与设计模式

编程模式(coding pattern)——一些专门为 JavaScript 语言开发出的最佳实践方案;
设计模式(design pattern)—这些模式与具体语言无关,它们主要来自那本著名的GoF 所著的《设计模式》一书。

编程模式

主要的模式有:
行为隔离;
命名空间;
初始化分支;
延迟初始(惰性初始);
配置对象;
私有变量和方法;
特权方法;
私有函数的公有化;
即时函数;
链式调用;
JSON。

网页三要素:内容(HTML);外观(CSS);行为(JavaScript)。

通常情况下,内容(HTML)中是不应该包含格式化元素的。可视化格式之类的元素应该属于外观层的东西,通常交由 CSS 来实现,这意味着我们应该:
 1.尽量避免在 HTML 标签中使用 style 属性;
 2.不要使用与外观有关的 HTML 标签,例如< font >; 
3.尽量根据语义需要来选择标签,而不是去考虑浏览器会如何绘制它们。例如,开发人员有时候对< div>标签的使用实际上不如< p>标签来得更合适。同理,我们应该更多地使用< strong>和< em>而不是< b>和< i>,因为后者更强调的是外观而不是语义。

要将外观与内容分开,有一种好方法就是对浏览器默认的绘制行为进行重置,例如YUI 库中的 reset.css。这样一来,浏览器默认的绘制方式就不会影响我们对语义标签的选择了。

行为也应该做到与内容及外观分离。行为通常是由JavaScript 负责定义的,且只由< script>标签来标记。这些脚本代码最好被存放在外部文件中。这意味着我们使用的不是类似于 onclick, onmouseover 这样的内嵌属性,而是
利用前几章中曾经介绍过的 addEventListener/attachEvent 方法来进行事件定义。
关于行为与内容的隔离,我们通常有以下几条原则性策略。
 1尽可能少用< script>标签。
 2尽量不要使用内嵌事件的处理方法。
 3尽量不要使用 CSS 表达式。
 4当 JavaScript 被用户禁用时,我们要动态地添加一些表示无目标的替换标记。
5 在内容末尾、< body>标签之前,插入一个 external.js 文件。

< script>标签被放置在< body>元素的最末。这么做是
因为载入 JavaScript 代码的过程会阻塞页面 DOM 的构建,甚至在某些浏览器中,一些需要下载的组件也会被阻塞。将< script>移动到页面底部可以确保它不会形成阻塞,并且这段 JavaScript 被载入后只会增强这个基本功能已经完整的页面。
另一种防止外部 JavaScript 文件阻塞页面的方法是将它们异步载入页面。这么做的话,我们就可以早一些开始载入它们。HTML5 为此提供了 defer 属性:
不幸的是,老式浏览器并不支持 defer 属性。但还好我们有另一种跨浏览器的方法来解决这一问题,并且这种方式新老浏览器都能接受。这种方式就是动态创建 script 节点,然后将它插入 DOM。换句话说,我们需要使用一些内联 JavaScript 代码来载入外部JavaScript 文件。这段代码可以放在文档的顶部,这样一来外部 JavaScript 文件就会早一些被载入:

为了减少命名冲突,我们通常都会尽量减少使用全局变量的机会。但这并不能根本解决问题,更好的办法是将变量和方法定义在不同的命名空间中。这种方法的实质就是只定义一个全局变量,并将其他变量和方法定义为该变量的属性。

不同的浏览器对于相同或相似的方法可能有不同的实现。
这时,您需要依据当前的浏览器的支持方式来选择对应的执行分支。这类分支可能有很多,因而可能会减缓脚本执行速度。
但非要等到运行时才能分支吗?我们完全可以在加载脚本时,在模块初始化的过程中就将部分代码进行分支处理。这显然更有利于提高效率。利用 JavaScript 代码可以动态定义的特性,我们可以为不同的浏览器定制不同的实现方法。
一旦上述脚本被执行,我们就定义了与浏览器特性相关的 addListener()和
removeListener()方法。如此,当它们再次被调用时,就不需要再探测浏览器特性了,脚本会执行得更快。
在检查浏览器特性时,请尽量不要对一个特性做过多的假设。

惰性初始模式与上面的初始化分支模式很相似。不同之处在于,该模式下的分支只有在相关函数第一次被调用时才会发生—即只有函数被调用时,它才会以最佳实现改写自己。在初始化分支模式中,模块初始化时 if 分支必然会发生,而在惰性初始模式中,这可能根本就不会发生—因为某些函数可能永远不会被调用。同时,惰性初始模式也会使得初始化过程更为轻量,因为不需要再做分支检测。

可以用对象来代替多个参数。也就是说,让这些参数都成为某一个对象的属性。这在面对一些配置型参数时会显得尤为适合,因为它们中往往存在多个缺省参数。简而言之,用单个对象来替代多个参数有以下几点优势:

1 不用考虑参数的顺序。
2 可以跳过某些参数的设置。
3 函数的扩展性更强,可以适应将来的扩展需要。
4 代码的可读性更好,因为在代码中我们看到的是配置对象的属性名称。

特权函数(这个概念是由 Douglas Crockford 提出的)实际上只是一些普通的公共函数,但它们却可以访问对象的私有方法或属性。其作用就像一座桥梁,将私有特性以一种可控的方式暴露给外部使用者。

假设我们定义了一个函数,但并不想让外界修改它,于是将其设为私有。但有时候我们又希望让某些外部代码能访问到它,这该如何实现呢?解决方案是将这个私有函数赋值给一个公有属性。

另一个保证全局命名空间不被污染的模式是,把代码封装在一个匿名函数中并立即调用。如此一来,该函数中的所有变量都是局部的(假设我们使用了 var 关键字),并在函数返回时被销毁(前提是它们不属于闭包)。
即时函数也可用于创建和返回对象。

模块模式包括以下几个部分。
1命名空间:用于减少模块之间的命名冲突。
2即时函数:用于提供私有作用域以及初始化操作。
3私有属性与方法。
4作为返回值的对象:该对象作为模块提供公共 API。

通过链式调用模式,我们可以在单行代码中一次性调用多个方法,就好像它们被链接在了一起。当我们需要连续调用若干个彼此相关的方法时,会带来很大的方便。实际上,我们就是通过前一个方法的结果(即返回对象)来调用下一个方法的,因此不需要中间变量。

JSON 本身实际上是一种轻量级的数据交换格式。当使用 XMLHttpRequest()接收服务器端的数据时,通常使用的就是 JSON 而不是 XML。JSON 是 JavaScript Object Notation的缩写,它除了使用极为方便之外,没有什么特别的。JSON 格式由对象和数组标记的数据构成。

设计模式

设计模式大概分为三种:
创建型模式:涉及对象的创建与初始化。
结构型模式:描述了如何组合对象以提供新的功能。
行为型模式:描述了对象之间如何通信。

单件是一个创建型的设计模式,它主要考虑的是创建对象的方式。当我们需要创建一种类型或一个类的唯一对象时,就可以使用该模式。在一般的语言中,这意味着这一个类只能被创建一个实例对象,如果之后再尝试创建该对象的话,代码就只会返回原来的实例。
但由于 JavaScript 本身没有类的概念,所以单件成为了默认行为,也是最自然的模式。每个对象都是一个单件。
JavaScript 中最基本的单件模式实现是使用对象文本标识法:

工厂模式也属于来创建对象的创建型模式。当我们有多个相似的对象而又不知道应该先使用哪种时,就可以考虑使用工厂模式。在该模式下,代码将会根据具体的输入或其他既定规则,自行决定创建哪种类型的对象。

装饰器模式是一种结构型模式,它与对象的创建无关,主要考虑的是如何拓展对象的功能。也就是说,除了使用线性式(父-子-孙)继承方式之外,我们也可以为一个基础对象创建若干个装饰对象以拓展其功能。然后,由我们的程序自行选择不同的装饰器,并按不同的顺序使用它们。在不同的程序中我们可能会面临不同的需求,并从同样的装饰器集合中选择不同的子集。

观察者模式(有时也称为发布-订阅模式)是一种行为型模式,主要用于处理不同对象之间的交互通信问题。观察者模式中通常会包含两类对象。
1一个或多个发布者对象:当有重要的事情发生时,会通知订阅者。
2 一个或多个订阅者对象:它们追随一个或多个发布者,监听它们的通知,并作出相应的反应。

观察者对象中应该有如下属性和方法:
 1.由回调函数构成的订阅者数组。
 2.用于添加和删除订阅者的 addSubscriber()和 removeSubscriber()方法。
 3.publish()方法,授受并传递数据给订阅者。
 4.make()方法,将任意对象转变为一个发布者并为其添加上述方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值