在 JavaScript 中全局变量经常会引起命名冲突, 甚至有时侯重写变量不是按照想像中的顺序来. 避免全局变量名冲突的最好办法还是创建命名空间, 接下来千锋重庆小编就给大家分享在 JavaScript 中创建命名空间的几种常用方法.
JavaScript 的执行环境由各种各样的全局变量构成, 这些全局变量先于函数执行环境而创建, 这些全局变量都挂载于 "全局对象" 下. 当名称有冲突时就会产生一些不可控的问题, 比如命名冲突, 代码的脆弱性, 难以测试等.
在编程开发中合理的使用命名空间可以避免相同的变量或对象名称产生的冲突, 而且命名空间也有助于组织代码有更强的可维护性和可读性. JavaScript 中虽然没有提供原生的命名空间支持, 但我们可以使用其他的方法 (对象和闭包) 实现类似的效果.
1, 单一全局变量
JavaScript 中一个流行的命名空间模式是选择一个全局变量作为主要的引用对象, 因为每个可能的全局变量都成为唯一全局变量的属性, 也就不用再创建多个全局变量, 也就避免了和其他声明的冲突. 不过单一全局变量模式已经在不少的 JavaScript 类库中使用, 如: YUI 定义了唯一的 YUI 全局对象, jQuery 定义了 由其他类库使用时使用 jQuery 等. 示例如下:
- var myApplication = (function() {
- function() {
- //***
- },
- return {
- //**
- }
- })();
web 前端开发学习 Q-q-u-n:784783012 , 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频)
2, 命名空间前缀
命名空间前缀模式其思路非常清晰, 就是选择一个独特的命名空间, 然后在其后面声明声明变量, 方法和对象. 示例如下:
- var = myApplication_propertyA = {
- };
- var = myApplication_propertyA = {
- };
- function myApplication_myMethod() {
- //***
- }
从某种程度上来说, 它确实减少了命名冲突的发生概率, 但其并没有减少全局变量的数目, 在使用这种模式时一定要特别注意.
3, 对象字面量表示法
对象字面量模式可以认为是包含一组键值对的对象, 每一对键和值由冒号分隔, 键也可以是代码新的命名空间. 示例如下:
- var myApplication = {
- // 可以很容易的为对象字面量定义功能
- getInfo:function() {
- //***
- },
- // 可以进一步支撑对象命名空间
- models:{
- },
- views:{
- pages:{
- }
- },
- collections:{
- }
- };
对象字面量为我们提供了优雅的键 / 值语法, 我们可以非常便捷的组织代码封装不同的逻辑或功能, 而且可读性, 可维护性, 可扩展性极强.
4, 嵌套命名空间
嵌套命名空间模式可以说是对象字面量模式的升级版, 它也是一种有效的避免冲突模式, 因为即使一个命名空间存在, 它也不太可能拥有同样的嵌套子对象, 示例如下:
- var myApplication = myApplication || {
- };
- // 定义嵌套子对象
- myApplication.routers = myApplication.routers || {
- };
- myApplication.routers.test = myApplication.routers.test || {
- };
Web 前端开发学习 Q-q-u-n:784783012 , 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频)
当然, 我们也可以选择声明新的嵌套命名空间或属性作为索引属性, 如:
myApplication[´routers´] = myApplication[´routers´] || {};
使用嵌套命名空间模式可以使代码易读且有组织性, 而且相对安全, 不易产生冲突, 其弱点是如果我们的命名空间嵌套过多会增加浏览器的查询工作量.
5, 立即调用的函数表达式
立即调用函数 (IIFE) 实际上就是匿名函数, 被定义后立即被调用. IIFE 是用于封装应用程序逻辑的常用方法, 以保护它免受全局名称空间的影响. 示例如下:
- // 命名空间和 undefined 作为参数传递, 确保:
- // 1. 命名空间可以在局部修改, 不重写函数外部上下文
- // 2.undefined 的参数值是确保 undefined, 避免 ES5 规范里定义的 undefined
- (function (namespace, undefined) {
- // 私有属性
- var foo = "foo";
- bar = "bar";
- // 公有方法和属性
- namespace.foobar = "foobar";
- namespace.sayHello = function () {
- say("Hello World!");
- };
- // 私有方法
- function say(str) {
- console.log("You said:" str);
- };
- })(Windows.namespace = Windows.namespace || {
- });
Web 前端开发学习 Q-q-u-n:784783012 , 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频)
可扩展性是任何可伸缩命名空间模式的关键, 使用 IIFE 可以轻松实现这一目的, 我们可以再次使用 IIFE 给命名空间添加更多的功能.
6, 命名空间注入
命名空间注入是 IIFE 的另一个变体, 从函数包装器内部为一个特定的命名空间 "注入" 方法和属性, 使用 this 作为命名空间代理, 这种模式的优点是可以将功能行为应用到多个对象或命名空间. 示例如下:
- var myApplication = myApplication || {
- };
- myApplication.utils = {
- };
- (function () {
- var value = 5;
- this.getValue = function () {
- return value;
- }
- // 定义新的子命名空间
- this.tools = {
- };
- }).apply(myApplication.utils);
- (function () {
- this.diagnose = function () {
- return "diagnose";
- }
- }).apply(myApplication.utils.tools);
同样的方式在普通的 IIFE 上扩展功能, 仅仅将上下文作为参数传递并修改, 而不是仅仅使用 this
如果你经常被全局变量冲突困扰, 一定要牢记 JavaScript 命名空间知识点.
这里推荐一下我的前端学习交流扣 qun:784783012 , 里面都是学习前端的, 从最基础的 html+CSS+JS[炫酷特效, 游戏, 插件封装, 设计模式] 到移动端 HTML5 的项目实战的学习资料都有整理, 送给每一位前端小伙伴. 2019 最新技术, 从企业招聘人才需求 到怎么学习前端开发, 和学习什么内容都有免费系统分享. 好友都在里面学习交流, 每天都会有大牛定时讲解前端技术!
点击: 加入
来源: http://www.jianshu.com/p/a38189f84a78