隐藏”作用域中的变量和函数所带来的另一个好处,是可以避免同名标识符之间的冲突, 两个标识符可能具有相同的名字但用途却不一样,无意间可能造成命名冲突。冲突会导致 变量的值被意外覆盖。 例如:
function foo() { function bar(a) {
i = 3; // 修改for循环所属作用域中的i
console.log( a + i );
}
for (var i=0; i<10; i++) {
bar( i * 2 ); // 糟糕,无限循环了!
} }
foo();
bar(..)内部的赋值表达式i = 3意外地覆盖了声明在foo(..)内部for循环中的i。在这 个例子中将会导致无限循环,因为 i 被固定设置为 3,永远满足小于 10 这个条件。 bar(..) 内部的赋值操作需要声明一个本地变量来使用,采用任何名字都可以,var i = 3; 就可以满足这个需求(同时会为 i 声明一个前面提到过的“遮蔽变量”)。另外一种方法是 采用一个完全不同的标识符名称,比如var j = 3;。但是软件设计在某种情况下可能自然 而然地要求使用同样的标识符名称,因此在这种情况下使用作用域来“隐藏”内部声明是 唯一的最佳选择。
1. 全局命名空间
变量冲突的一个典型例子存在于全局作用域中。当程序中加载了多个第三方库时,如果它 们没有妥善地将内部私有的函数或变量隐藏起来,就会很容易引发冲突。 这些库通常会在全局作用域中声明一个名字足够独特的变量,通常是一个对象。这个对象 被用作库的命名空间,所有需要暴露给外界的功能都会成为这个对象(命名空间)的属 性,而不是将自己的标识符暴露在顶级的词法作用域中。 例如:
var MyReallyCoolLibrary = { awesome: "stuff", doSomething: function() {
// ... },
doAnotherThing: function() {
// ...
2. 模块管理
另外一种避免冲突的办法和现代的模块机制很接近,就是从众多模块管理器中挑选一个来 使用。使用这些工具,任何库都无需将标识符加入到全局作用域中,而是通过依赖管理器 的机制将库的标识符显式地导入到另外一个特定的作用域中。 显而易见,这些工具并没有能够违反词法作用域规则的“神奇”功能。它们只是利用作用 域的规则强制所有标识符都不能注入到共享作用域中,而是保持在私有、无冲突的作用域 中,这样可以有效规避掉所有的意外冲突。
标签:function,变量,作用域,js,规避,冲突,var,标识符 From: https://blog.51cto.com/u_16298168/9355714