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

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

静态命名空间

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. [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!

    一.背景 最近的项目在用maven 进行install的时候,发现老师在控制台输出警告:[WARNING] Using platform encoding (UTF-8 actually) to co ...

  2. ActiveX控件打包成Cab置于网页中自动下载安装 [转]

    http://blog.sina.com.cn/s/blog_520c32270100nopj.html 做过ActiveX控件的朋友都知道,要想把自己做的ActiveX控件功能放在自己的网页上使用, ...

  3. C#中异常处理和Java的区别

    捕获异常,同样是try...catch...,这个完全一样: 抛出异常,同样是throw,这个完全一样: 函数抛出怎样的异常,Java中可以用throws定义,而C#中不用定义,相当于throws E ...

  4. java实验8-Java输入输出流

    1 读写文件 [实验目的] (1)掌握文本文件的读写方法. (2)掌握随机文件的读写方法. (3)掌握InputStream.OutputStream抽象类的基本使用. (4)掌握FileInputS ...

  5. valid-palindrome——判断带符号数字字母的字符串是否为回文

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  6. 命令行查看w3wp进程信息

    用windbg.mdbg等调试器调试时,当出现多个w3wp进程并且用户名相同,需要区分每个w3wp进程对应的PID(进程ID)和应用程序池信息. 我们用以下方式得到每个w3wp进程的详细信息. Win ...

  7. JavaScript 工厂模式和订阅模式

    设计模式的好处: 代码规范 // 例如表单验证,两个 input ,一个用户名,一个密码 // 通常做法是 function checkUser(){ //..... } function check ...

  8. 小贝_mysql select连接查询

    select连接查询 简要: 一.union联合查询 二.左右内连接 一.union联合查询 作用: 把2次或多次查询结果合并起来 具体: (表1查询结果) union (表2查询结果) 运行: 先算 ...

  9. caffe2 安装与介绍

    http://blog.csdn.net/yan_joy/article/details/70241319 标签: 深度学习 2017-04-19 15:31 5970人阅读 评论(0) 收藏 举报 ...

  10. JavaScript读书笔记(1)

    从今天开启每天看书记笔记模式,<JavaScript高级程序设计(第3版)> 1. Javascript最初是为了解决输入验证器的问题,现在已经发展成一门复杂的语言: 2.  语言标准为E ...