您好,欢迎来到暴趣科技网。
搜索
您的当前位置:首页JavaScript中的命名空间

JavaScript中的命名空间

来源:暴趣科技网


学习了解过PHP的同学都知道命名空间这个概念吧,在复杂的系统中会有N多的函数、对象,语言提供的、架构预定义的,这么多的函数和对象,由于编程规范要求起有实际意义的名字,难免会重名发生错误调用,而有了命名空间烦恼就没有了,不但可以分类组织函数与对象,还可以形成隔离,解决重名问题。

使用JavaScript就没有这么舒服了,Javascript只有函数作用域,什么块儿啊、神马文件啊统统都认为是一个命名空间的,有时候因为一些重名问题导致的错误让人莫名其妙,难以调试解决。

一个简单的例子

<input type="button" value="test" onclick="alert();"/>
 <script type="text/javascript">
 function alert(){
 //.......
 test2();
 //.......
 }
 function test2(){
 alert('test2')
 }
 </script>

在个例子在不同的浏览器下有不同表现,IE会报Stack over flow, Firefox会死掉。。反正都会报错,很简单的错误,代码中自定义了一个alert函数,在alert函数中调用了test2函数,test2函数中意图调用window的alert方法,这样循环调用了,也许看了你会说这么明显的错误谁会犯,但是如果自定义的方法叫close(这个经常会出现吧),然后内部调用了一个外部文件的函数,该函数调用了window的close方法,这样错误是不是隐蔽了很多呢。

简单的命名空间

由于JavaScript没有文件作用域,不同的函数分散在不同的文件中,甚至由不同的人编写,重名的概率大大增加。是不是足够小心就可以了呢?也不尽然,还有些意外情况,比如经常会用到继承,于是写了一个没出现过的函数名extend,不料在EcmaScript5中加入了extend函数,命名空间的必要性就体现出来了。

JavaScript有函数的作用域,可以利用这点把自定义的函数写到一个函数体内,这样函数内的变量、对象、函数就像在一个命名空间内一样和外部隔离。

<input type="button" value="test" onclick="(new namespace()).alert();"/>
 
 <script type="text/javascript">
 function namespace(){
 this.alert=function(){
 console.log('test');
 }
 }
 </script>

这样自定义的alert方法就不会和window的alert冲突了。

简单进化

这样可以是可以,但也有问题,最大的问题在于调用方式复杂而丑陋!每次调用的时候都要实例化对象,然后调用其方法,简单修改代码让其实现自动实例化。

<input type="button" value="test" onclick="NS.alert();"/>
 <script type="text/javascript">
 (function namespace(){
 this.alert=function(){
 console.log('test');
 }
 window.NS=this;
 })();
 </script>

要看明白上面代码首先要了解一下“立即执行函数”(江湖人是这么称呼的)的技巧结构类似这样

(function xxx(){
 //function body 
 })();

这样写xxx函数就可以在定义完后自动执行,看起来神奇,其实上面写法可以拆成这样

function xxx(){
 //function body 
 }
xxx();

就是定义一个函数,然后使用括号语法调用,而函数定义外面的一层括号只起到将函数声明转为函数定义表达式,因为只有表达式才可以使用括号调用。看明白这些妖蛾子之后上面代码就简单了,在自定义namespace函数最后把this赋值为window的NS属性,在调用的时候直接使用NS.xx就可以了。看起来好了很多。

美化一下

上面的写法看起来不错了,但是函数名namespace貌似是多余的了,可以美化一下

(function (){
 this.alert=function(){
 console.log('test');
 }
 window.NS=this;
 })();

变成了一个立即执行的匿名函数,美化了一些,不过看起来还是怪怪的,对呀,明明是实例化的function,为什么方法定义不写到prototype中呢,匿名函数怎么写prototype。。,还得动动脑筋

(function(){
 var _NS=function(){
 }
 _NS.prototype.alert=function(){
 console.log('test');
 }
 window.NS=new _NS();
 })();

写几个有用的函数

querySelector和querySelectorAll是W3C提供的新的查询接口,但是名字好长,自己写个简单的,innerHTML属性也常用到,写个简单版仿jQuery的html方法

(function () {
 var _NS = function () {
 }
 _NS.prototype.select = function (selector,context) {
 var context = context || document;
 return context.querySelectorAll(selector);
 }
 _NS.prototype.isArrayLike=function(obj){
 if(obj instanceof Array){
 return true;
 }

 var length=obj.length;
 if ( obj.nodeType === 1 && length ) {
 return true;
 }
 return false;
 }
 _NS.prototype.html = function (obj,value) {
 var isArray=this.isArrayLike(obj), i=0;
 if (typeof value == 'string') {
 if (!isArray) {
 obj.innerHTML = value;
 } else {
 var length = obj.length;
 while (i < length) {
 obj[i].innerHTML = value;
 i += 1;
 }
 }
 } else {
 if (!isArray) {
 return obj.innerHTML;
 } else {
 return obj[0].innerHTML;
 }
 }
 }
 window.NS = new _NS();
 })();

命名空间有效防止函数名/类名和其他人的冲突,在使用多个第三方框架或类库的时候,一旦冲突,唯一能作的就是放弃其中一个。
从事Web开发不可避免要接触JavaScript,目前最新版本的JavaScript还是不支持命名空间,所以命名冲突的问题凸显无疑,想象一下你引用了两个js文件,却发现由于命名问题导致你不得不放弃其中一个,从而导致多写了许多代码,无疑是十分令人沮丧的。在JavaScript新版本引入命名空间概念之前,发扬自立更生精神和创造性是我们程序员的基本义务;

相关文章:

PHP命名空间详细使用方法

js命名空间写法示例代码

Copyright © 2019- baoquwan.com 版权所有

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务