javascript 命名空间的首选技术
Posted
技术标签:
【中文标题】javascript 命名空间的首选技术【英文标题】:Preferred technique for javascript namespacing 【发布时间】:2011-09-26 20:05:16 【问题描述】:如果我不开始使用某种命名空间技术,我的代码将会变得一团糟。我对大型 javascript 项目的编程相对较新,但在 C++/java/python 等系统编程方面有丰富的经验。
基本上,我试图确定创建 javascript 命名空间的首选方法,以及每种方法的优缺点。
例如,我可以使用以下三种方法之一:
var proj.lib.layout =
"centreElem":
function (elem, W, H)
,
"getAbsolutePosition":
function (elem)
;
或
var proj.lib.layout = ;
(function()
var l = proj.lib.layout;
l.centreElem = function (elem, winW, winH)
..
l.getAbsolutePosition = function (elem)
..
)();
或
var proj.lib.layout = new function()
function centreElem(elem, W, H)
..
function getAbsolutePosition(elem)
..
this.centreElem = centreElem;
this.getAbsolutePosition = getAbsolutePosition;
();
显然还有其他方法可以做到这一点,但这些是我看到和想到的第一个。谁能说有一种“最好”的技术,或者至少指出一些优点/缺点,我可以从中评估哪种技术最适合我?
【问题讨论】:
Javascript Namespace Declaration的可能重复 【参考方案1】:基本上所有三个示例都使用相同的“命名空间”技术,即创建一个基本对象(您的命名空间),然后用您的函数对其进行扩充。
通常根命名空间是大写的:
if (typeof (MYAPP) == "undefined" || !MYAPP)
var MYAPP=
;
然后您可以通过各种方式向此基础对象添加功能。在您的代码中,您显示了其中的三个,但每个都得到相同的结果,您可以调用这两个函数:
proj.lib.layout.centreElem(elem, W, H);
proj.lib.layout. getAbsolutePosition(elem);
【讨论】:
【参考方案2】:请注意,您必须先创建所有中间对象,然后才能分配给这样的子对象:
window.one.two.three = ; // fails
window.one = two: three: ;
考虑编写命名空间方法,以便统一命名空间代码。例如:
window.proj = ;
// n - String - A string representing a namespace to create on proj
// returns an object you can assign values to
window.proj.namespace = function(n) /* ... */ ;
(function(NS)
NS.myMethod = function() ;
NS.myOtherMethod = function() ;
NS.myProperty = "FOO";
)(proj.namespace('lib.layout'));
assert(proj.lib.layout.myProperty === "FOO");
【讨论】:
起初我对namespace()
函数的含义感到困惑,但现在我的意思是执行命名空间的通用创建,例如设置中间命名空间。好主意,谢谢。然后我假设您批准并推荐这种形式的命名空间声明(自执行匿名函数)。
顺便说一句,这在 Javascript 世界中通常被称为“模块模式”。
另外,我考虑过包含一个命名空间函数实现,但它是一个相当常见的框架函数。基本算法是在“.”上拆分,循环遍历各个部分,创建必要的中间对象。最后,返回对最后创建的对象的引用。【参考方案3】:
Google Closure Javascript Library 使用这种风格(与您的任何示例都不完全一样)
goog.math.clamp = function(value, min, max)
return Math.min(Math.max(value, min), max);
;
我会坚持这种简单的风格。不要为自动执行的匿名函数包装而烦恼。您示例中的那个实际上并没有做任何有用的事情。
【讨论】:
是的,我这样做是为了避免为每个函数键入完整的链。把它放在一个自动执行的函数中意味着临时 l 不会在全球范围内存在。它也稍微快一点,我假设你不必在赋值期间遍历链,并且在同一命名空间中引用变量/函数的函数体也不需要指定链。【参考方案4】:我的首选方法是使用单个对象(其名称通常很短,2-3 个字符,全部大写)作为包含所有其他对象的命名空间。
下面显示的方法(与您的第二个示例最接近)还显示了如何隐藏任何私有函数:
// In this example the namespace is "QP"
if (!QP)
var QP = ;
;
// Define all objects inside an closure to allow "private" functions
(function()
QP.examplePublicFunction = function()
...
function examplePrivateFunction()
...
)();
这是许多其他 JavaScript 库使用的方法,例如 json2.js
我从来没有真正觉得有必要将我的命名空间细分为子命名空间。
【讨论】:
以上是关于javascript 命名空间的首选技术的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript 中的命名空间技术,推荐吗?高性能?需要注意的问题?