JavaScript 命名空间
JavaScript 命名空间
什么是命名空间
命名空间 是一组 标识符、函数、方法等的容器。 它为其内容提供了一定程度的组织,以便可以很好地区分和组织。
为什么需要命名空间
我们一定从任何语言中都了解了 命名空间。 它的作用是,它不允许我们污染我们的代码库,并通过对代码进行逻辑分组并避免意外和预期的冲突来使它更干净。
为了实现这一点,我们需要做的是在应用程序中创建一个命名空间并使用它。
在任何现代应用程序中,命名空间 是必须拥有的,因为最终我们需要第三方库和组件。
命名空间在 JavaScript 中的重要性
不幸的是,JavaScript 默认不提供命名空间。 因此,我们在 JavaScript 中创建的任何内容(函数
、方法
、对象
、变量
)都是 全局
的,并且我们通过向其添加更多内容来继续污染该 全局命名空间
。
但好消息是我们可以 在 JavaScript 中创建命名空间,而且也很容易。
众所周知,在 JavaScript 中,一切都是一个对象,创建一个对象非常简单。 我们可以通过一些小的调整来轻松实现命名空间。
让我们看看 JavaScript 如何使所有东西都成为全局的
//declare a function
function calculateTax(item) {
return item.price * 1.40;
}
var product = function (cost) {
this.cost = cost;
this.getCost = function(){
return this.cost;
};
};
function doTaxCalculations() {
var p = new product(100);
alert(calculateTax(p.getCost()));
}
在上面的代码中,两个函数和类,这三个都位于全局空间中。
这是一个简单的代码库,但它包含 3 个全局项 (calculateTax
, product
, doTaxCalculations
)。
如果我们使用第三方库并且它们也包含相同的名称,这三个将会给我们带来麻烦。
例如,如果它在其他库之前使用,它将被库覆盖,反之亦然。
JavaScript 命名空间示例
在 JavaScript 中,它只不过是一个 单一的全局对象,它将包含我们所有的 函数、方法、变量等。 这里 ‘MYAPPLICATION
’ 作为 JavaScript 命名空间 并是唯一一个包含所有其他项目的 全局对象
。
var MYAPPLICATION = {
calculateTax: function (item) {
return item * 1.40;
},
product: function (cost) {
this.cost = cost;
this.getCost = function(){
return this.cost;
};
},
doTaxCalculations: function () {
var p = new MYAPPLICATION.product(100);
alert(this.calculateTax(p.getCost()));
}
}
要访问任何 方法 或 变量,您需要通过 MYAPPLICATION
获取它。
var newProduct = new MYAPPLICATION.product(200);
alert(p.getPrice());
不仅是像上面这样的单一命名空间,我们还可以创建 嵌套的 JavaScript 命名空间。
让我们看一个嵌套 JavaScript 命名空间的示例。
嵌套 JavaScript 命名空间
它只不过是一个 命名空间 内部的 命名空间,它为 复杂的 JavaScript 应用程序 提供了更好的 模块化。
var MYNESTEDAPPLICATION = {
MODEL: {
product: function (price) {
this.price = price;
this.getCost = function(){
return this.price;
};
}
},
LOGIC: {
calculateTax: function (item) {
return item * 1.40;
},
doCalculations: function () {
var p = new MYNESTEDAPPLICATION.MODEL.product(100);
alert(this.calculateTax(p.getCost()));
}
}
}
注意
Do your naming convention in such a manner that it will be self explanatory and not conflict other Library. May be I am not that good at those.
如果不存在则创建命名空间
像上面一样,我们使用一个单一的全局对象,但它可能与其他全局对象冲突。
为了避免这种情况,我们可以在创建它之前检查其是否存在,这是一个好习惯。
// not safe, if there's another object with this name we will overwrite it
var MYSAMPLEAPP = {};
// We need check before we create the namespace
if (typeof MYSAMPLEAPP === "undefined") {
var MYSAMPLEAPP = {};
}
// shorter version
var MYSAMPLEAPP = MYSAMPLEAPP || {};
上面是创建命名空间最安全的方法,但我们可以做的是通过编写一个函数来使其更容易,该函数将创建我们的 命名空间。
创建命名空间的函数
我们只需要使用一些参数调用一个简单的函数来创建我们的 命名空间。 然后,我们可以在该命名空间中定义所有函数和变量。
var MYNAMESPACE = MYNAMESPACE || {};
var newNamespace = MYNAMESPACE.createNameSpace("MYNAMESPACE.COUNTRY.STATES");
newNamespace.product = function(price) {
this.price = price;
this.getCost = function(){
return this.price;
}
};
MYNAMESPACE.createNameSpace = function (namespace) {
//get the namespace string and split it
var namespaceArr = namespace.split(".");
var parent = MYNAMESPACE;
// excluding the parent
if (namespaceArr[0] === "MYNAMESPACE") {
namespaceArr = namespaceArr.slice(1);
}
// loop through the array and create a nested namespace
for (var i = 0; i < namespaceArr.length; i++) {
var partname = namespaceArr[i];
// check if the current parent already has the namespace declared
// if it isn't, then create it
if (typeof parent[partname] === "undefined") {
parent[partname] = {};
}
// get a reference to the deepest element in the hierarchy so far
parent = parent[partname];
}
// empty namespaces created and can be used.
return parent;
};
基本上,createNameSpace
函数拆分 字符串
并从中创建一个嵌套命名空间。
MYNAMESPACE.createNameSpace("MYNAMESPACE.COUNTRY.STATES");
输出
var MYNAMESPACE = {
COUNTRY: {
STATES: {
}
}
}
命名空间别名
我们可以通过简单地将 命名空间 别名为一个局部变量来实现这一点
var state = MYNAMESPACE.COUNTRY.STATES;
使用 state
而不是整个命名空间来获取所有变量和函数。
注意
但是,上面关于 命名空间 的解决方案对于大多数情况来说是完全有效和有用的。
但可能存在某些情况,在这种情况下,这并不是最好的选择。
在这里,只有一个全局实例,但没有什么可以阻止我们直接访问内部变量。
不知何故,我们需要控制对 私有
变量的访问。 这可以通过 “使用模块创建模块化应用程序” 来实现,该模块将封装日期。
使用模块
MYAPP.MODEL.PRODUCTS.product = function(cost) {
//cost is the private variable
var cost = cost;
return {
isTaxable: true,
getCost: function(){
return cost;
}
};
};
cost
可以被该函数访问,因为它属于 闭包,否则它不能被直接访问。
isTaxable
和 getCost
是 公共
的。
有很多模式可以实现这一点。
例如,将所有内容设为私有,并公开我们需要公开的内容。
MYAPP.MODEL.PRODUCTS.product = function(cost){
//everything private
var cost = cost;
var isTaxable = true;
var getCost: function(){
return cost;
};
//expose what you need
return {
isTaxable: isTaxable,
getCost: getCost
};
};
尽管在上面编写的示例中可能存在一些安全问题,但我们可以使其越来越完美。
我们可以通过引用 命名空间 内的任何变量来阻止访问。 有很多我们可以遵循的模式来实现这一点。
结论
命名空间 的使用使 JavaScript 代码 模块化 和 结构化,也易于阅读、理解和修改。 因此,在不污染全局命名空间的情况下,我们可以实现所有这些,无论如何我们都必须使用 全局命名空间,但我们并没有在那里搞砸。
希望这有帮助。 感谢您的阅读。