龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

Javascript学习笔记之函数篇(六) : 作用域与命名空间(2)

时间:2014-11-28 11:05来源:网络整理 作者:网络 点击:
分享到:
由于 Javascript 没有块级作用域,这不仅将提升 var 表达式,同时也会使得 if 结构变得不够直观。 在上例中,尽管看上去 if 在对全局变量 goo 进行操作,实

由于 Javascript 没有块级作用域,这不仅将提升 var 表达式,同时也会使得 if 结构变得不够直观。
在上例中,尽管看上去 if 在对全局变量 goo 进行操作,实际上,由于变量 goo 被提升,所以修改的是局部变量。
如果没有对提升规则有所了解,你可能会认为下面的代码将会抛出 ReferenceError 错误。

复制代码 代码如下:

// check whether SomeImportantThing has been initialized
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}

当然上面的代码是没有错误的,因为在代码在运行前,var 表达式已经被提升到顶部。

复制代码 代码如下:

var SomeImportantThing;
// other code might initialize SomeImportantThing here, or not
// make sure it's there
if (!SomeImportantThing) {
    SomeImportantThing = {};
}

这里要推荐下 @nightire 凡哥的博文 《理解 JavaScript(二)》,里面对提升的讲解非常透彻。
名称解析顺序

当尝试在一个函数作用域内访问一个 foo 变量时,Javascript 将会按照下面的顺序查找:

当前作用域内是否有 var foo 的定义。
函数形参中是否有 foo 变量。
函数自身的名称是否为 foo。
跳到外层定义域,再从第一部开始查找起。
命名空间

一个最常见的问题就是命名冲突,这是因为 Javascript 只有一个全局作用域所带来的。但这个问题可以通过匿名的外部函数解决。

复制代码 代码如下:

(function() {
    // a self contained "namespace"
    window.foo = function() {
        // an exposed closure
    };
})(); // execute the function immediately

上例中的匿名函数被认为是表达式,所以它们会被执行。

复制代码 代码如下:

( // evaluate the function inside the parentheses
function() {}
) // and return the function object
() // call the result of the evaluation

当然我们也可以用其他方式来调用函数表达式,不同的结构,但是同样的效果。

复制代码 代码如下:

// A few other styles for directly invoking the
!function(){}()
+function(){}()
(function(){}());
// and so on...

总结

建议大家使用匿名的外部函数来将代码封装到空间内,这样不仅可以解决命名空间的冲突,同时也有利于程序的模块化。
此外,使用全局变量不是一个好习惯,这将带来高成本的维护代价而且容易产生错误。

命名空间同类型、函数、变量、模板等都属于实体(entity)。
实体的主要的共性是,可以具有名称。(此外,标签也可以具有名称,但它不是实体。)
而命名空间作用域是作用域中的一类统称,和块作用域、类作用域、函数原型作用域、函数作用域(仅对标签有效)并列。命名空间内声明的名称在命名空间作用域中。全局名称被认为在隐含的全局命名空间作用域中。

精彩图集

赞助商链接