全局变量应该由有系统范围相关性的对象们保留,并且它们的命名应该避免含糊并尽量减少命名冲突的风险。在实践中,这意味着你应该避免创建全局对象,除非它们是绝对必须的。
不过,恩,这些你早都知道了……
所以你对此是怎么做的?传统方法告诉我们,最好的消除全局策略是创建少数作为潜在模块和子系统的实际命名空间的全局对象。我将探索几种有关命名空间的方式,并以我基于 James Edwards 最近的一篇文章得到的一个优雅、安全和灵活的解决方案结束。
静态命名空间
我用静态命名空间
作为那些命名空间标签实际上硬编码的解决方案的涵盖性术语。是的,你可以将一个命名空间重新分配给另一个,不过新的命名空间将会引用和旧的那一个同样的对象。
1.通过直接分配
最基础的方法。这样非常冗长,并且如果你还想重命名这些命名空间,你就有得活儿干了。不过它是安全和清楚明白的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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
引用兄弟属性来使将来的维护更轻松一些,不过这有一点冒险因为没有什么能阻止你的那些命名空间里的方法被重新分配。
1 2 3 4 5 6 7 8 9 10 11 12 |
var myApp = {} myApp.id = 0; myApp.next = function() { return this.id++; } myApp.reset = function() { this.id = 0; } myApp.next(); //0 myApp.next(); //1 var getNextId = myApp.next; getNextId(); //NaN whoops! |
2.使用对象字面量
现在我们只需要引用命名空间名一次,因此之后改变名字更简单了一些(假设你还没反复引用这个命名空间)。仍有一个危险是this
的值可能会抛出一个『惊喜』 – 不过假设在一个对象字面结构里定义的对象不会被重新分配相对安全一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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。此外,任何没有包括在返回值中的变量将永远保持私有,只对引用他们的公开方法可见。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var myApp = (function() { var id= 0; return { next: function() { return id++; }, reset: function() { id = 0; } }; })(); window.console && console.log window.console && console.log 不过,恩,这些你早都知道了…… 所以你对此是怎么做的?传统方法告诉我们,最好的消除全局策略是创建少数作为潜在模块和子系统的实际命名空间的全局对象。我将探索几种有关命名空间的方式,并以我基于 James Edwards 最近的一篇文章得到的一个优雅、安全和灵活的解决方案结束。 静态命名空间我用 1.通过直接分配最基础的方法。这样非常冗长,并且如果你还想重命名这些命名空间,你就有得活儿干了。不过它是安全和清楚明白的。
你也可以通过使用
2.使用对象字面量现在我们只需要引用命名空间名一次,因此之后改变名字更简单了一些(假设你还没反复引用这个命名空间)。仍有一个危险是
3.模块模式我发现自己最近用
|