这又是一个新的开始,对象的重要性不言而喻。在JavaScript中创建对象是十分容易的,之前聊过的对象字面量和构造函数都可以达到目的。但是本篇中,我们越过那些方法,以寻求一些额外的对象创建模式。

  本篇内容,我们将学到命名空间(namespace),依赖声明(dependency declaration)、模块模式(module pattern)、沙箱模式(sandbox pattern)。它们都可以帮助您组织应用程序代码的结构,并且降低隐含的全局变量带来的后果。其他讨论的主题包括私有和特权成员、对象常量、链和一个启发类的方式以以定义构造函数。

一、命名空间模式

  命名空间(namespace)有助于减少程序中所需要的全局变量的数量,并且同时还有助于避免命名冲突或过长的名字前缀。

  JavaScript语言的语法中并没有内置命名空间,但是这种特征是非常容易实现的。可以为应用程序或库创建一个(理想上最好只有一个)全局对象,然后可以将所有功能添加到该全局对象中,从而在有大量函数、对象和其他变量的情况下并不会污染全局范围。

  1. // 5个全局变量
  2. // 警告:反模式
  3. // 构造函数
  4. function Parent() {}
  5. function Child() {}
  6.  
  7. // 一个变量
  8. var some_var = 1;
  9.  
  10. // 一些对象
  11. var module1 = {};
  12. module1.data = {a:1,b:2};
  13. var module2 = {};
  14.  
  15. // 可以通过为应用程序创建一个全局对象这种方式来重构上面这种类型的代码:
  16. // 之后:1个全局变量
  17. // 全局变量
  18. var MYAPP = {};
  19.  
  20. // 构造函数
  21. MYAPP.Parent = function () {};
  22. MYAPP.Child = function () {};
  23.  
  24. // 一个变量
  25. MYAPP.some_var = 1;
  26.  
  27. // 一个对象容器
  28. MYAPP.modules = {};
  29.  
  30. // 嵌套对象
  31. MYAPP.modules.module1 = {};
  32. MYAPP.modules.module1.data = {a:1,b:2};
  33. MYAPP.modules.module2 = {};

  对于全局命名空间对象的名称,可以任意选择,比如以应用程序或库的名称、域名或公司名来命名。通常根据公约,以全部大写的方式来命名全局变量,这样比较显眼(当然,常量也是这样)。

  这种模式是一种组织代码的命名空间的好方法,不仅可以避免您代码中的命名冲突,并且还可以避免在同一个页面中您的代码和第三方代码之间的命名冲突。

  当然,这样的方式也有一些缺点:

  • 需要输入更多的字符,每个变量和函数前都要附加前缀,总体上增加了需要下载的代码量。
  • 仅有一个全局实例意味着任何部分的代码都可以修改该全局实例。
  • 长嵌套名字意味着更长(更慢)的属性解析查询时间。

  本篇后面介绍的沙箱模式可以解决以上这些缺点。

通用命名空间函数

  由于程序负责性的增加、代码的某些部分被分割成不同的文件,以及使用条件包含语句等多个因素,仅假设您的代码是第一个定义某个命名空间或它内部的属性,这种做法已经变得不再安全。添加到命名空间的一些属性可能已经存在,这导致可能会覆盖它们。因此,在添加一个属性或者创建一个命名空间之前,最好是首先检查它是否已经存在:

  1. // 不安全的代码
  2. var MYAPP = {};
  3. // 更好的代码风格
  4. if(typeof MYAPP === 'undefined') {
  5. var MYAPP = {};
  6. }
  7. // 或者用更短的语句
  8. var MYAPP = MYAPP || {};

  可以看到这些附加的检查是如何循序导致大量的重复代码。比如,如果想要定义MYAPP.modules.module2,必须构造三次检查,每次检查都要针对定义的一个对象或者属性。这也就是为什么需要一个可以很方便地处理命名空间细节的可重用函数的原因。让我们称该函数为namespace()并以如下方式使用:

  1. // 使用命名空间函数
  2. MYAPP.namespace('MYAPP.modules.module2');
  3.  
  4. // 相当于以下代码
  5. var MYAPP = {
  6. modules:{
  7. module2:{}
  8. }
  9. };

  接下来是一个命名空间函数的示例。这个实现是非破坏性的,也就是说,如果已经存在一个命名空间,便不会再重新创建它:

  1. var MYAPP = MYAPP || {};
  2.  
  3. MYAPP.namespace = function (ns_string) {
  4. var parts = ns_string.split('.'),
  5. parent = MYAPP,
  6. i;
  7.  
  8. // 剥离最前面的冗余全局变量
  9. if(parts[0] === "MYAPP"){
  10. parts = parts.slice(1);
  11. }
  12.  
  13. for(i = 0;i < parts.length; i += 1){
  14. // 如果不存在就创建一个属性
  15. if(typeof parent[parts[i]] === 'undefined'){
  16. parent[parts[i]] = {};
  17. }
  18. parent = parent[parts[i]];
  19. }
  20. return parent;
  21. }
  22. // 本实现使下列所有这些用法都能正常运行:
  23. // 将返回值赋给一个全局变量
  24. var module2 = MYAPP.namespace('MYAPP.modules.module2');
  25. console.log(module2 === MYAPP.modules.module2);
  26.  
  27. // 忽略最前面的‘MYAPP’
  28. console.log(MYAPP.namespace('modules.module51'));
  29.  
  30. // 长命名空间
  31. console.log(MYAPP.namespace('once.upon.a.time.there.was.this.long.short.nested.property'));

二、声明依赖关系

  JavaScript库通常是模块化且依据命名空间组织的,这使您能够仅包含所需的模块。例如,在YUI2库中有一个充当命名空间的全局变量YAHOO,而模块是该全局变量的属性,比如YAHOO.util.Dom和YAHOO.util.Event。

  在您的函数或模块顶部声明代码所依赖的模块是一个非常好的主意。该声明仅涉及创建一个局部变量并使其指向所需的模块。

  1. var myFunction = function () {
  2. // 依赖
  3. var event = YAHOO.util.Event,
  4. dom = YAHOO.util.Dom;
  5.  
  6. // 使用事件和DOM变量
  7. // 其他逻辑
  8. };

  这是一个及其简单的模式,但是它却有很多优点:

  • 显式的依赖声明向您代码的用户表明了他们确定需要的特定脚本文件已经包含在该页面中。
  • 在函数顶部的前期声明可以使您很容易地发现并解析依赖。
  • 解析局部变量的速度总是要比解析全局变量要快,甚至比使用全局变量的嵌套属性还要快,这导致了更好的性能。当使用这种依赖声明模式时,全局符号解析仅会在函数中执行一次。在此之后将会使用局部变量,这种解析速度也快很多。
  • 类似于YUICompressor和Google闭包编译器的这些高级小工具可以重命名局部变量(即,压缩),这导致了更小的代码量,但是这些工具从不会对全局变量进行重命名,因为这样做是不安全的。

  

  这篇就到这里了,说实话就是很小的两个点,但是这两个point,确实会给你的代码带来不错的性能提升。好了,下篇文章见。

《JavaScript 模式》读书笔记(5)— 对象创建模式1的更多相关文章

  1. 《Javascript高级程序设计》读书笔记之对象创建

    <javascript高级程序设计>读过有两遍了,有些重要内容总是会忘记,写一下读书笔记备忘 创建对象 工厂模式 工厂模式优点:有了封装的概念,解决了创建多个相似对象的问题 缺点:没有解决 ...

  2. 设计模式---对象创建模式之原型模式(prototype)

    一:概念 原型模式(Prototype Pattern) 实际上就是动态抽取当前对象运行时的状态 Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例.使用Protot ...

  3. C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder

    part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...

  4. 《Javascript模式》之对象创建模式读书笔记

    引言: 在javascript中创建对象是很容易的,可以使用对象字面量或者构造函数或者object.creat.在接下来的介绍中,我们将越过这些方法去寻求一些其他的对象创建模式. 我们知道js是一种简 ...

  5. 《JavaScript 模式》读书笔记(5)— 对象创建模式4

    我们学完了大部分对象创建模式相关的内容,下面还有一些小而精的部分. 七.对象常量 JavaScript中没有常量的概念,虽然许多现代的编程环境可能为您提供了用以创建常量的const语句.作为一种变通方 ...

  6. 《JavaScript模式》第5章 对象创建模式

    @by Ruth92(转载请注明出处) 第5章:对象创建模式 JavaScript 是一种简洁明了的语言,并没有其他语言中经常使用的一些特殊语法特征,如 命名空间.模块.包.私有属性 以及 静态成员 ...

  7. 深入理解JavaScript系列(47):对象创建模式(上篇)

    介绍 本篇主要是介绍创建对象方面的模式,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式1:命名空间(namespace) 命名空间可以减少全局命名所需的数量,避免命名冲突或过度. ...

  8. 深入理解JavaScript系列(48):对象创建模式(下篇)

    介绍 本篇主要是介绍创建对象方面的模式的下篇,利用各种技巧可以极大地避免了错误或者可以编写出非常精简的代码. 模式6:函数语法糖 函数语法糖是为一个对象快速添加方法(函数)的扩展,这个主要是利用pro ...

  9. 设计模式---对象创建模式之构建器模式(Builder)

    一:概念 Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种.Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象 ...

随机推荐

  1. PM2.5如何引发心脏病的?

    过去的几十年里,科学家们一点一滴地积累起关于空气污染如何威胁人类健康的新认识.他们的注意力大多集中在肺部疾病,包括癌症上面.对空气污染具体危害的认识越来越多,但是对污染的控制和治理却显得举步维艰.面对 ...

  2. STM32F103驱动ADS1118

    ADS1118 作为常用温度测量芯片被越来越多的开发者熟知,TI官方给出的是基于 MSP430 的驱动测试程序,由于 STM32 的普及,闲暇中移植了 MSP430 的 ADS1118 驱动程序到 S ...

  3. 【Art】抗疫路上,温暖相伴

    2020年3月. 本应是春暖花开的时节,武汉却是寒冷的,整个中国也是寒冷的. 疫情将人们逼得退无可退,只能待在家里看着电视新闻与手机上一个个数字不断跳动,等待着它们背后前线的无数命悬一线的战士的胜利讯 ...

  4. 一文看懂Java序列化

    一文看懂Java序列化 简介 Java实现 Serializable 最基本情况 类的成员为引用 同一对象多次序列化 子父类引用序列化 可自定义的可序列化 Externalizable:强制自定义序列 ...

  5. 8421BCD转余3码Verilog HDL的设计(1)

    近期阅读Verilog HDL高级数字设计(第二版)中,遇到了串行比特流BCD码转余3码转换器的设计,比较独特的是: (1)该转换器的输入为1位串行比特流,输出也为1位串行比特流. BCD码与余三码的 ...

  6. CSS中"position:relative"属性与文档流的关系

    前言 近期遇到一个问题--"position:relative"到底会不会导致元素脱离文档流?主流观点是不会,但都给不出一个有说服力的论据.最后我自己佐证了一番,总算有了个结果:& ...

  7. css实战#用css画一个中国结

    大家好!今天跟大家分享一个用 css 画中国结的教程.最终效果如下: 大家如果感兴趣可以参考我的源码:gitHub地址 首先,我们定义好画中国结需要的结构: <div class="k ...

  8. 每个 JavaScript 工程师都应当知道的 10 个面试题

    1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程 ...

  9. ts文件的编译和运行

    hello.ts代码 function sayHello(person: string): string { return 'Hello, ' + person; } let user = 'Tom' ...

  10. java中的对象 方法 引用 等一些抽象的概念是什么意思呢?

    2020-03-14 最近这一段时间有点忙,好久都没有更新博客了,之后我会一直坚持下去的,和大家一同进步的. 这段时间一直在学java,相信刚开始学习java的小白,刚开始接触那么些抽象的概念一定和我 ...