Js中的命名空间(namespace)

访客3年前黑客文章1140

全局变量应该由有系统局限相关性的工具们保留,而且它们的命名应该制止模糊并只管削减命名冲突的风险。在实践中,这意味着你应该制止建立全局工具,除非它们是绝对必须的。 不外,恩,这些你早都知道了……

以是你对此是怎么做的?传统方式告诉我们,更好的消除全局计谋是建立少数作为潜在模块和子系统的现实命名空间的全局工具。我将探索几种有关命名空间的方式,并以我基于 James Edwards最近的一篇文章获得的一个优雅、平安和天真的解决方案竣事。


静态命名空间

我我用静态命名空间作为那些命名空间标签现实上硬编码的解决方案的涵盖性术语。是的,你可以将一个命名空间重新分配给另一个,不外新的命名空间将会引用和旧的那一个同样的工具。

1.通过直接分配

最基础的方式。这样异常冗长,而且若是你还想重命名这些命名空间,你就有得活儿干了。不外它是平安和清晰明晰的。

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

你也可以通过使用this引用兄弟属性来使未来的维护更轻松一些,不外这有一点冒险由于没有什么能阻止你的那些命名空间里的方式被重新分配。

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


2.使用工具字面量

现在我们只需要引用命名空间名一次,因此之后改变名字更简朴了一些(假设你还没频频引用这个命名空间)。仍有一个危险是this的值可能会抛出一个『惊喜』 – 不外假设在一个工具字面结构里界说的工具不会被重新分配相对平安一点。

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


3.模块模式

我发现自己最近用模块模式更多。逻辑被一个方式包装从全局域隔离开了(通常是自挪用的),它返回一个代表这个模块公然接口的工具。通过立刻挪用这个方式并分配效果给一个命名空间变量,我们就锁住了这个命名变量中模块的 API。此外,任何没有包罗在返回值中的变量将永远保持私有,只对引用他们的公然方式可见。

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

如上工具字面量例子,命名空间名字可以容易替换,不外另有分外优势:工具字面量是四班的 – 它全是关于属性分配,没有支持逻辑的空间。此外,所有属性必须被初始化,而且属性值无法容易跨工具引用(因此,好比,内部闭包就不可能使用了)。模块模式没有任何上述约束,而且给我们分外的隐私福利。


动态命名空间

我们也可以将这一节称为命名空间注入。命名空间由一个直接引用方式包装内部的署理代表 – 这意味着我们不再需要打包分配给命名空间的返回值。这让命名空间界说变得更天真而且让拥有多个存在于自力命名空间中(或者甚至在全局上下文中)的模块的自力实例。动态命名空间支持模块模式的所有特征并附加直观和可读性强的优势。


4.提供命名空间参数

在这里我们只是将命名空间作为参数传给自挪用方式。变量id是私有的,由于他并没有被分配给context。

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

我们甚至可以把context设置给全局工具(通过一个字的改变!)。这是库主们的伟大财富 – 他们可以将他们的特征包装在一个自挪用函数中,然后让用户来决议它们是不是全局的(John Resig 在他写 JQuery 时就是一个这个理论的早期接纳者)。

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


5.用this作为命名空间署理

James Edwads 最近公布的一篇文章激起了我的兴趣。《My Favorite JavaScript Design Patter》
 显然被许多评论者误解了,他们以为他可能也是借助于模块模式。这篇文章宣传了多种手艺(可能导致了读者的疑惑),但是在它的焦点部门是一点我已经修改并呈现为一个命名空间工具的很天才的器械。

这个模式的美就在于它仅仅是根据这个语言被设计的方式使用 – 不多不少、不投契也不取巧。此外由于命名空间是通过this关键字(它在给定的执行上下文中是稳固的)注入的,它不可能被意外修改。

var myApp = {};
(function() {    var id = 0;    this.next = function() {        return id++;    
    };    this.reset = function() {
        id = 0;     
    }
}).apply(myApp);    

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

更棒的是,apply(以及call) API 提供了与上下文和参数自然的隔离 – 因此给模块建立者通报附加参数异常清洁。下面的例子表明晰这一点,而且展示了如何自力于多个命名空间来运行模块。

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

固然若是我们若是我们需要一个全局 id 生成器,异常简朴……

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

这个我们作为例子使用的 id 生成器工具并没有表现出这个模式的所有潜力。通过包裹一整个库和使用this关键字作为命名空间的替身,我们使得用户在任何他们选择的上下文中运行这个库很轻松(包罗全局上下文)。

//library codevar protoQueryMooJo = function() {  
    //everything}//user codevar thirdParty = {};
protoQueryMooJo.apply(thirdParty);


其他的思量

我希望制止命名空间嵌套。它们很难追踪(对人和电脑都是)而且它们会让你的代码由于一些杂乱无章的器械变得许多。如 Peter Michaux 指出的,深度嵌套的命名空间可能是那些视图重新建立他们熟悉和热爱的长包链的老派 Java 开发者的遗产。

通过 .js 文件来牢固一个单独的命名空间也是可以的(虽然只能通过命名空间注入或者直接分配每一个变量),不外你应该对依赖郑重些。此外将命名空间绑定到文件上可以辅助读者更容易弄清整个代码。

由于 JavaScript 并没有正式的命名空间结构,以是有许多自然形成的方式。这个观察只详细说明晰其中的一部门,可能有更好的手艺我没有发现。我很愿意知道它们。

译文:@雷森图喵喜客 
链接:http://chengkang.me/2016/06/21/Namespacing%20in%20JavaScript/



思源资源网:分类流动

1.阿里云: 本站现在使用的是阿里云主机,平安/可靠/稳固。点击领取2000米代金券、领会最新阿里云产物的种种优惠流动点击进入

相关文章

最新世界大学排名情况怎么样(世界大学排名前

最新世界大学排名情况怎么样(世界大学排名前

QS 世界大学排名™已成为世界最具权威的大学排名之一,榜上有名的皆属一流大学。 Quacquarelli Symonds提供全球高等教育领域前沿信息及资讯,为多家世界权威媒体提供信息及数据。 1...

怎么盗我女友的微信聊天记录又不被他发现呢

每日好文     声音总是能够给我们留下很多美好的回忆,过往我们...

黑客为什么不盗QQ号(黑客只要知道号就可以盗号吗?)

黑客为什么不盗QQ号(黑客只要知道号就可以盗号吗?)

本文目录一览: 1、怎么才能让QQ号不被盗? 2、为什么QQ号有人盗啊? 3、怎么才可以让自己你的qq号永远不会被别人盗 4、我的QQ好像被盗了,但哪个黑客却暂时不盗我的号,我的问题答案又...

安徽牛肉汤什么牌子好(安徽哪里的牛肉汤最好

安徽牛肉汤什么牌子好(安徽哪里的牛肉汤最好

​​ 淮南牛肉汤是苏豫鲁皖沪一带家喻户晓的名小吃,选用了几十种滋补药材及卤料按一定的比例经传统工艺炮制,久经熬制而成。味道醇厚,鲜香爽辣,营养美味,有滋补养身的食疗功效。 ​ 原料有:黄牛牛肉牛...

同步老公支付宝他会发现吗_远程查看对象微信聊天

魅族官方信息将于4月13日公布魅族pro6手机上,那麼魅族pro6和魅蓝Metal哪家好?魅族pro6和魅蓝Metal配备主要参数有哪些不一样?文中将出示魅族pro6和魅蓝Metal差别比照测评供大伙...

何韵诗 浮夸(劳斯莱斯何韵诗)

劳斯和莱斯都是花样男子劳斯原是个校队的优秀种子莱斯只喜爱读书偏偏他俩早见晚见每日着住同样纯白衬衣罗曼史开场於相邻的桌椅不过二人。 何韵诗《劳斯莱斯》MP3我发你concertyy那版的稍等 歌曲名:劳...