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

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

一、命名空间模式

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

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

// 5个全局变量
// 警告:反模式
// 构造函数
function Parent() {}
function Child() {} // 一个变量
var some_var = 1; // 一些对象
var module1 = {};
module1.data = {a:1,b:2};
var module2 = {}; // 可以通过为应用程序创建一个全局对象这种方式来重构上面这种类型的代码:
// 之后:1个全局变量
// 全局变量
var MYAPP = {}; // 构造函数
MYAPP.Parent = function () {};
MYAPP.Child = function () {}; // 一个变量
MYAPP.some_var = 1; // 一个对象容器
MYAPP.modules = {}; // 嵌套对象
MYAPP.modules.module1 = {};
MYAPP.modules.module1.data = {a:1,b:2};
MYAPP.modules.module2 = {};

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

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

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

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

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

通用命名空间函数

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

// 不安全的代码
var MYAPP = {};
// 更好的代码风格
if(typeof MYAPP === 'undefined') {
var MYAPP = {};
}
// 或者用更短的语句
var MYAPP = MYAPP || {};

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

// 使用命名空间函数
MYAPP.namespace('MYAPP.modules.module2'); // 相当于以下代码
var MYAPP = {
modules:{
module2:{}
}
};

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

var MYAPP = MYAPP || {};

MYAPP.namespace = function (ns_string) {
var parts = ns_string.split('.'),
parent = MYAPP,
i; // 剥离最前面的冗余全局变量
if(parts[0] === "MYAPP"){
parts = parts.slice(1);
} for(i = 0;i < parts.length; i += 1){
// 如果不存在就创建一个属性
if(typeof parent[parts[i]] === 'undefined'){
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
}
// 本实现使下列所有这些用法都能正常运行:
// 将返回值赋给一个全局变量
var module2 = MYAPP.namespace('MYAPP.modules.module2');
console.log(module2 === MYAPP.modules.module2); // 忽略最前面的‘MYAPP’
console.log(MYAPP.namespace('modules.module51')); // 长命名空间
console.log(MYAPP.namespace('once.upon.a.time.there.was.this.long.short.nested.property'));

二、声明依赖关系

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

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

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

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

  • 显式的依赖声明向您代码的用户表明了他们确定需要的特定脚本文件已经包含在该页面中。
  • 在函数顶部的前期声明可以使您很容易地发现并解析依赖。
  • 解析局部变量的速度总是要比解析全局变量要快,甚至比使用全局变量的嵌套属性还要快,这导致了更好的性能。当使用这种依赖声明模式时,全局符号解析仅会在函数中执行一次。在此之后将会使用局部变量,这种解析速度也快很多。
  • 类似于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. 苹果会放弃iPhone吗?

    ​苹果会放弃iPhone吗?一般来讲,这是一个相当白痴的问题,苹果放弃iPhone的概率比唐僧放弃取经的概率要低20倍.前段时间回老家,正在学习英语的小侄子问我:"叔叔,苹果用英语怎么说呀? ...

  2. RxJava 2.x 源码分析

    本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...

  3. C++走向远洋——34(友元函数,成员函数和一般函数的区别)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:youyuan.cpp * 作者:常轩 * 微信公众号:Worl ...

  4. 【深入理解Java虚拟机 】类加载器的命名空间以及类的卸载

    类加载器的命名空间 每个类加载器又有一个命名空间,由其以及其父加载器组成 类加载器的命名空间的作用和影响 每个类加载器又有一个命名空间,由其以及其父加载器组成 在每个类加载器自己的命名空间中不能出现相 ...

  5. Mysql报错:Authentication .....Reading from the stream has failed

    连接Mysql5.7版本的数据库出现报错:Authentication to host '171.13.164.***' for user 'root' using method 'mysql_nat ...

  6. 小白学 Python 数据分析(12):Pandas (十一)数据透视表(pivot_table)

    人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...

  7. 量化投资学习笔记37——《Python机器学习应用》课程笔记10

    用KNN算法来进行数字识别,还是用sklearn自带的digits数据集. coding:utf-8 KNN算法实现手写识别 from sklearn import neighbors from sk ...

  8. CentOS7.5源码编译安装mysql5.7.29

    #查看系统版本 [root@ctos3 ~]# cat /etc/redhat-release CentOS Linux release (Core) #下载源码包,需要注意的是mysql5.7 编译 ...

  9. js轮询及踩过的坑

    背景 下午四点,天气晴朗,阳光明媚,等着下班产品:我希望页面上的这个数据实时变化开发:···,可以,用那个叫着WebSocket的东西,再找一个封装好框架,如:mqtt(感觉自己好机智)产品:要开发好 ...

  10. 峰哥说技术:08-Spring Boot整合FreeMarker视图

    Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 08  峰哥说技术:Spring Boot整合FreeMarker视图 前面带着大家整合了Thymelea ...