JS编程建议——69:使用模块化规避缺陷

简介: 69:使用模块化规避缺陷

建议69:使用模块化规避缺陷
使用函数和闭包可以构建模块。所谓模块,就是一个提供接口却隐藏状态与实现的函数或对象。通过使用函数构建模块,可以完全摒弃全局变量的使用,从而规避JavaScript语言缺陷。全局变量是JavaScript最为糟糕的特性之一,在一个大中型Web应用中,全局变量可能会带来不可预料的后果。
例如,要为String扩展一个deentityify方法,其设计任务是寻找字符串中的HTML字符实体并将其替换为对应的字符。在一个对象中保存字符实体的名字及与之对应的字符是有意义的。
可以把deentityify放到一个全局变量中,但全局变量存在很多潜在危害。可以把deentityify定义在该函数本身中,但会带来运行时的损耗,因为在该函数每次被执行时,这个方法都会被求值一次。理想的方式是将deentityify放入一个闭包,而且也许还能提供一个增加更多字符实体的扩展方法。
String.method('deentityify', function() {

var entity = {
    quot : '"',
    lt : '<',
    gt : '>'
};
return function() {
    return this.replace(/&([^&;]+);/g, function(a, b) {
        var r = entity[b];
        return typeof r === 'string' ? r : a;
    });
};

}());
在上面代码中,为String类型扩展了一个deentityify方法,它调用字符串的replace方法来查找以“&”开头和以“;”结束的子字符串。如果这些字符可以在字符实体表entity中找到,那么就将该字符实体替换为映射表中的值。deentityify方法用到了一个正则表达式:
return this.replace(/&(1+);/g, function(a, b) {

var r = entity[b];
return typeof r === 'string' ? r : a;

});
在最后一行使用()运算符立刻调用刚刚构造出来的函数。这个调用所创建并返回的函数才是deentityify方法。
document.writeln('<">'.deentityify()); // <">
模块利用了函数作用域和闭包来创建绑定对象与私有成员的关联。在这个示例中,只有deentityify方法才有权访问字符实体表entity这个数据对象。模块开发的一般形式是:一个定义了私有变量和函数的函数,利用闭包创建可以访问到的私有变量和函数的特权函数,最后返回这个特权函数,或者把它们保存到可访问的地方。
使用模块可以避免全局变量的滥用,从而保护信息的安全性,实现优秀的设计实践。使用这种模式也可以实现应用程序的封装,或者构建其他实例对象。
模块模式通常结合实例模式使用。JavaScript的实例就是用对象字面量表示法创建的,对象的属性值可以是数值或函数,并且属性值在该对象的生命周期中不会发生变化。模块通常作为工具为程序其他部分提供功能支持。通过这种方式能够构建比较安全的对象。
下面代码构造一个用来产生序列号的对象。serial_maker()函数将返回一个用来产生唯一字符串的对象,这个字符串由两部分组成:字符前缀+序列号。这两部分可以分别使用set_prefix和set_seq方法进行设置,然后调用实例对象的gensym方法读取这个字符串。当执行该方法时,都会自动产生唯一一个字符串。
var serial_maker = function() {

var prefix = '';
var seq = 0;
return {
    set_prefix : function(p) {
        prefix = String(p);
    },
    set_seq : function(s) {
        seq = s;
    },
    gensym : function() {
        var result = prefix + seq;
        seq += 1;
        return result;
    }
};

};
var seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym(); //"Q1000"
var unique = seqer.gensym(); //"Q1001"
seqer包含的方法都没有用到this或that,因此没有办法“损害”seger,除非调用对应的方法,否则无法改变prefix或seq的值。由于seqer对象是可变的,所以它的方法可能会被替换掉,但替换后的方法依然不能访问私有成员。seqer就是一组函数的集合,而且这些函数被授予特权,拥有使用或修改私有状态的能力。如果把seqer.gensym作为一个值传递给第三方函数,这个函数就能通过它产生唯一字符串,却不能通过它来改变prefix或seq的值。


  1. &;
相关文章
|
2月前
|
存储 JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果+1
JavaScript编程实现tab选项卡切换的效果+1
|
2月前
|
JavaScript UED
js之模块化(2)
js之模块化(2)
|
3月前
|
JavaScript 前端开发 编译器
解锁JavaScript模块化编程新纪元:从CommonJS的基石到ES Modules的飞跃,探索代码组织的艺术与科学
【8月更文挑战第27天】随着Web应用复杂度的提升,JavaScript模块化编程变得至关重要,它能有效降低代码耦合度并提高项目可维护性及扩展性。从CommonJS到ES Modules,模块化标准经历了显著的发展。CommonJS最初专为服务器端设计,通过`require()`同步加载模块。而ES Modules作为官方标准,支持异步加载,更适合浏览器环境,并且能够进行静态分析以优化性能。这两种标准各有特色,但ES Modules凭借其更广泛的跨平台兼容性和现代语法逐渐成为主流。这一演进不仅标志着JavaScript模块化的成熟,也反映了整个JavaScript生态系统的不断完善。
50 3
|
8天前
|
自然语言处理 JavaScript 前端开发
JavaScript闭包:解锁编程潜能,释放你的创造力
【10月更文挑战第25天】本文深入探讨了JavaScript中的闭包,包括其基本概念、创建方法和实践应用。闭包允许函数访问其定义时的作用域链,常用于数据封装、函数柯里化和模块化编程。文章还提供了闭包的最佳实践,帮助读者更好地理解和使用这一强大特性。
11 2
|
2月前
|
JavaScript 前端开发 开发者
js之模块化(1)
js之模块化(1)
|
21天前
|
缓存 JavaScript 前端开发
Node.js模块化的基本概念和分类及使用方法
Node.js模块化的基本概念和分类及使用方法
23 0
|
2月前
|
JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果
JavaScript编程实现tab选项卡切换的效果
|
2月前
|
JavaScript 前端开发
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
|
2月前
|
JavaScript
js之模块化(3)
js之模块化(3)
|
2月前
|
JavaScript 前端开发 安全
JavaScript编程实现字符和字符串翻转
JavaScript编程实现字符和字符串翻转