js中的命名空间
尽量不要使用全局变量,防止环境污染和命名冲突。
所以,将全局变量放在一个命名空间下,是一个好的解决方案。
静态命名空间
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中的命名空间的更多相关文章
- js中创建命名空间的几种写法
在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子: var sayHello = function() { return 'Hel ...
- 在js中创建命名空间的几种写法
在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子: var sayHello = function() { return 'H ...
- 关于js中namespace命名空间模式
命名空间有助于减少程序中所需要的全局变量的数量,并且同时有助于避免命名冲突或过长的名字前缀. 关于命名空间的例子: /** * 创建全局对象MYAPP * @module MYAPP * @title ...
- JavaScript中创建命名空间
引用:http://ourjs.com/detail/538d8d024929582e6200000c 在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺 ...
- 在JavaScript中创建命名空间的几种写法
在JavaScript中全局变量经常会引起命名冲突,甚至有时侯重写变量也不是按照你想像中的顺序来的,可以看看下面的例子: var sayHello = function() { return 'Hel ...
- JS中的自执行函数
本来规划的是2013年,狠狠的将JS学习下,谁知计划赶不上变化,计划泡汤了.13年的我对JS来说可以说是属于跟风,对它的理解和认识也仅仅是皮毛而已,也是因为要完成<ArcGIS API for ...
- js中静态函数与变量
一 私有变量和函数 js中没有概念上的私有,公有也没有静态和非静态相关概念,有的只能是通过作用于来模仿 函数的块级作用域使得函数内部成员可以不被外部所访问,比如我们使用块级作用于定义一个类 //定义一 ...
- js中的面向对象入门
什么是对象 我们先来看高程三中是如何对对象进行定义的 "无序属性的集合,其属性可以包括基本值.对象或者函数",对象是一组没有特定顺序的的值.对象的没个属性或方法都有一个俄名字,每个 ...
- Day046--JavaScript-- DOM操作, js中的面向对象, 定时
一. DOM的操作(创建,追加,删除) parentNode 获取父级标签 nextElementSibling 获取下一个兄弟节点 children 获取所有的子标签 <!DOCTYPEhtm ...
随机推荐
- 从零开始开发iPhone,教你如何在真机调试iPhone应用程序
对于真机调试,首先要在苹果网站上注册APP ID,以及购买iPhone Develop Program(iDP) 开发者授权,99美元.然后要创建证书请求CSR,创建步骤如下:设置OCSP和CRL为关 ...
- navicat小经验和快捷键
1.有时按快捷键Ctrl+F搜某条数据的时候搜不到,但是能用sql查出来,这是怎么回事? Ctrl+F只能搜本页数据,不在本页的数据搜不到,navicat每页只显示1000条数据.在数据多的时候nav ...
- require.js使用
无可奈何,二开项目用了require.js! 一道槛是挨不过去了 require官网: http://requirejs.org/ require.js cdn: <script src=&qu ...
- 多选checkbox
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Spring <context:annotation-config> 和 <context:component-scan>区别
转自:http://www.cnblogs.com/leiOOlei/p/3713989.html <context:annotation-config> 和 <context:co ...
- android等待旋转圆圈动画
先创建一个动画的xml文件例如以下 <? xml version="1.0" encoding="utf-8"?> <animation-li ...
- PCIE、UART、I2C、SMBUS、SPI、eSPI、USB、PS2、CAN、SDIO等数据传输协议
M.2 wife一般支持USB.SDIO.PCIE三种传输
- Django-Rest-Framework部分源码流程分析
class TestView(APIView): ''' 调用这个函数的时候,会自动触发authentication_classes的运行,所以会先执行上边的类 ''' authentication_ ...
- NumPy事例练习
因为排版问题直接把jupyter里的截图过来了:暂时就写了这么点小例子,建议在ipython notebook中做测试
- LeetCode:判断最长前缀
之前一直忽略了一个问题就是:给定的空字符串数组 char* longestCommonPrefix(char** strs, int strsSize) { char* result; if(strs ...