JavaScript 原生不支持命名空间,易导致多文件引入时的函数名冲突。本文介绍通过构造函数创建空白对象来模拟命名空间,并演示如何定义子命名空间及扩展原型方法。同时对比了对象字面量定义法,解析 prototype.js 中常用的树状结构写法,帮助开发者避免全局变量污染。
JavaScript 命名空间模拟基础
JavaScript 代码中最常见的语法格式是定义函数,即 function xxx(){/*code...*/}。在实际开发中,往往存在大量函数定义,这极易引发命名冲突,尤其是在引入多个 JS 文件时,冲突现象尤为显著。因此,引入命名空间机制显得十分必要。
JavaScript 语言本身并未内置命名空间概念,开发者需要通过对象来模拟实现这一功能。
例如,可以定义一个专门用于创建命名空间的类:
function NameSpace(){
}
这是一个构造函数,但它并不执行任何具体操作,后续代码将展示与评论相关的实现:
var comment = new NameSpace();
comment.list = function(){/*code...*/};
comment.counter = 0;
上述代码中,第一行创建了一个名为 comment 的空白对象,即所谓的命名空间;第二、三行则在该空间下定义了两个成员:一个方法和一个计数器。调用时,可以使用 comment.list() 或 comment.counter++ 等方式访问。
子命名空间与对象字面量定义
接下来创建子命名空间:
comment.add = new NameSpace();
comment.add.post = function(){/*code...*/}
comment.add.check = function(){}
引入命名空间的核心目的是避免函数名重复。上述过程也可以采用如下方式定义:
var comment = {
list : function(){/*code...*/},
add : {
post : function(){/*code...*/},
check : function(){/*code...*/}
}
}
prototype.js 中大量使用了这种定义方式。虽然这种方式在视觉上更像一棵树,但当节点增多时,查找节点关系会变得困难。命名空间的做法则是横向描述这种关系树,将层次关系直接体现在字面量上。两种方法效果一致,但书写风格各有特点。
原型链方法扩展
此外,还可以扩展一个方法:
NameSpace.prototype.appendChild = function(ns){
for (var key in ns){
this[key] = ns[key];
}
return this;
}
NameSpace.prototype.copyChild = NameSpace.prototype.appendChild;