尽量不要使用全局变量,防止环境污染和命名冲突。

所以,将全局变量放在一个命名空间下,是一个好的解决方案。

静态命名空间

1. 直接赋值

这是最基本的方法,但是它很啰嗦,你得重复书写多次变量名。好处是它很安全,并且不会产生歧义。

 var myApp = {}

 myApp.id = ;

 myApp.next = function() {
return myApp.id++;
} myApp.reset = function() {
myApp.id = ;
} window.console && console.log(
myApp.next(),
myApp.next(),
myApp.reset(),
myApp.next()
); //0, 1, undefined, 0

你可以在命名空间函数中使用this来指代对象,但是要考虑到函数被重新分配是this将指向不明。

 var myApp = {}

 myApp.id = ;

 myApp.next = function() {
return this.id++;
} myApp.reset = function() {
this.id = ;
} myApp.next(); //
myApp.next(); //
var getNextId = myApp.next;
getNextId(); //NaN whoops!

2. 使用对象字面量方法

和上面的方法相比,下面如果要改变命名空间的名字将会很方便。但是仍然要注意使用this存在一定的风险。

 var myApp = {

     id: ,

     next: function() {
return this.id++;
}, reset: function() {
this.id = ;
}
}
window.console && console.log(
myApp.next(),
myApp.next(),
myApp.reset(),
myApp.next()
) //0, 1, undefined, 0

3. 模块模式

模块模式的好处是它将全局变量保存在了一个马上执行的函数包装器(a function wrapper)中,函数包装器将返回一个相当于模块公共接口的对象。同时,没有在函数包装器中return 的变量将是私有变量,只对引用它的公共函数可见。

 var myApp = (function() {

     var id= ;

     return {
next: function() {
return id++;
}, reset: function() {
id = ;
}
};
})(); window.console && console.log(
myApp.next(),
myApp.next(),
myApp.reset(),
myApp.next()
) //0, 1, undefined, 0

正如上面对象字面量方法一样,这里的命名空间名字可以很容易也很方便修改。但是对象字面量方法比较死板——它全是关于属性的定义,不能支持逻辑的书写,并且所有的属性必须被初始化且属性之间的值不能很简单的通过引用传递给另一个属性(所以,举例而言,内部闭包是不可能的)。模块模式相比而言没有上述限制,并且还拥有保护私有变量的特点。

动态命名空间

我们也可以叫做namespace injection. 命名空间被代理(proxy)表示,代理直接指向了函数包装器(the function wrapper)内部——这意味着我们不再需要绑定一个return给命名空间。这使得命名空间的定义更加灵活。动态命名空间有模块命名模式的所有好处,并且比模块模式更加直观和易于阅读。

4. 应用一个命名空间参数 Supply a Namespace Argument

这里我们简单的将命名空间作为一个变量传递给自己执行的函数。变量id是私有变脸,因为它没有定义给context变量。

 var myApp = {};
(function(context) {
var id = ; context.next = function() {
return id++;
}; context.reset = function() {
id = ;
}
})(myApp); window.console && console.log(
myApp.next(),
myApp.next(),
myApp.reset(),
myApp.next()
) //0, 1, undefined, 0

我们甚至可以将context设置成全局对象(只要改变一个单词就可以啦!)

 var myApp = {};
(function(context) {
var id = ; context.next = function() {
return id++;
}; context.reset = function() {
id = ;
}
})(this); window.console && console.log(
next(),
next(),
reset(),
next()
) //0, 1, undefined, 0

5. 使用this关键字作为命名空间代理(a Namespace Proxy)

使用this关键字作为命名空间的好处是,this关键字是在给予的执行环境中是静态的,它不会偶然改变。

 var myApp = {};
(function() {
var id = ; this.next = function() {
return id++;
}; this.reset = function() {
id = ;
}
}).apply(myApp); window.console && console.log(
myApp.next(),
myApp.next(),
myApp.reset(),
myApp.next()
); //0, 1, undefined, 0

因为apply和call函数是将this和指定的函数对象绑定,所以上述(function(){ ...... }).apply(命名空间),匿名函数里面的this一定指向命名空间。

下面解释了apply和call函数执行环境绑定的功能:

 var subsys1 = {}, subsys2 = {};
var nextIdMod = function(startId) {
var id = startId || ; this.next = function() {
return id++;
}; this.reset = function() {
id = ;
}
}; nextIdMod.call(subsys1);
nextIdMod.call(subsys2,); window.console && console.log(
subsys1.next(),
subsys1.next(),
subsys2.next(),
subsys1.reset(),
subsys2.next(),
subsys1.next()
) //0, 1, 1000, undefined, 1001, 0

当然,想和全局环境绑定,超级简单.....

 nextIdMod();   

 window.console && console.log(
next(),
next(),
reset(),
next()
) //0, 1, undefined, 0

使用apply和call的最大好处是可以随便使用任何你想绑定的环境对象。

 

其他考虑:

我没有使用内嵌的命名空间,因为它们很难跟踪,并且它们会将你的代码变得臃肿。对喜欢包装链(package chains )的怀旧Java码农而言,复杂的内嵌命名空间很符合他们的胃口。

js没有官方的命名空间的概念,所以你可以随心所欲大展身手创建自己的解决方案。

原文链接:https://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/

js中的命名空间的更多相关文章

  1. js中创建命名空间的几种写法

    在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子: var sayHello = function() { return 'Hel ...

  2. 在js中创建命名空间的几种写法

    在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子:   var sayHello = function() { return 'H ...

  3. 关于js中namespace命名空间模式

    命名空间有助于减少程序中所需要的全局变量的数量,并且同时有助于避免命名冲突或过长的名字前缀. 关于命名空间的例子: /** * 创建全局对象MYAPP * @module MYAPP * @title ...

  4. JavaScript中创建命名空间

    引用:http://ourjs.com/detail/538d8d024929582e6200000c   在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺 ...

  5. 在JavaScript中创建命名空间的几种写法

    在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子: var sayHello = function() { return 'Hel ...

  6. JS中的自执行函数

    本来规划的是2013年,狠狠的将JS学习下,谁知计划赶不上变化,计划泡汤了.13年的我对JS来说可以说是属于跟风,对它的理解和认识也仅仅是皮毛而已,也是因为要完成<ArcGIS API for ...

  7. js中静态函数与变量

    一 私有变量和函数 js中没有概念上的私有,公有也没有静态和非静态相关概念,有的只能是通过作用于来模仿 函数的块级作用域使得函数内部成员可以不被外部所访问,比如我们使用块级作用于定义一个类 //定义一 ...

  8. js中的面向对象入门

    什么是对象 我们先来看高程三中是如何对对象进行定义的 "无序属性的集合,其属性可以包括基本值.对象或者函数",对象是一组没有特定顺序的的值.对象的没个属性或方法都有一个俄名字,每个 ...

  9. Day046--JavaScript-- DOM操作, js中的面向对象, 定时

    一. DOM的操作(创建,追加,删除) parentNode 获取父级标签 nextElementSibling 获取下一个兄弟节点 children 获取所有的子标签 <!DOCTYPEhtm ...

随机推荐

  1. UITableView 滚动时使用reloaddata出现 crash'-[__NSCFArray objectAtIndex:]: index (1) beyond bounds (0)' Crash

    例子: - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)in ...

  2. 将可执行程序的内存空间扩展到3GB(windows)

    为了告知操作系统这个应用程序可以支持/3GB方式,我们需要往exe 文件头中添加一个 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志.添加的方式很简单: 在你的系统的 Progra ...

  3. Tyvj3308毒药解药题解

    题目大意 这些药都有可能在治愈某些病症的同一时候又使人患上某些别的病症--经过我天才的努力.最终弄清了每种药的详细性能,我会把每种药能治的病症和能使人患上的病症列一张清单给你们,然后你们要依据这张清单 ...

  4. hibernater-validator jar包冲突的问题

    在引用hibernater-validator jar包时一直抛出异常,在引用带有该包的项目,或者同时在一个项目中使用该包和validator包都会抛出以下异常 最后发现是在Eclipse环境下,不能 ...

  5. vue2.0 自定义指令

    Vue指令 Vue的指令以v-开头,作用在HTML元素上,将指令绑定在元素上,给绑定的元素添加一些特殊行为. 例如: <h1 v-if="yes">Yes</h1 ...

  6. sql分级汇总

    --測试数据 create table tb([DB-ID] varchar(10),ENTITY varchar(10),DATE varchar(10),[CUST-NO] int,AMOUNT ...

  7. Android自己定义View的实现方法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了.回 ...

  8. Effective Go(官方文档)笔记

    Effective Go(官方文档)笔记 自己主动局部变量提升(编译期完毕?):return &...; 内置函数: new/make copy, append delete range(这是 ...

  9. mysql + php 中文乱码 全是? 解决方法

    在my.ini文件中找到[client]和[mysqld]字段,在下面均加上default-character-set=utf8,保存并关闭,重启服务器 在window下重启失败,这是因为你安装了高版 ...

  10. android中的常见对话框

    在android中对话框是一种常见的操作,常见的对话框有下面几种: 以下是xml布局文件: <LinearLayout xmlns:android="http://schemas.an ...