深入浅出的JavaScript的作用域与命名空间

作用域与命名空间

尽管 Java 支持一对花括号创建的代码段,但是并不支持块级作用域; 而仅仅支持 函数作用域。

注意:如果 return 对象的左括号和 return 不在一行上就会出错。

Java 中没有显式的命名空间定义,这就意味着所有对象都定义在一个全局共享的命名空间下面。

每次引用一个变量,Java 会向上遍历整个作用域直到找到这个变量为止。 如果到达全局作用域但是这个变量仍未找到,则会抛出 ReferenceError异常。

隐式的全局变量

上面两段脚本效果不同。脚本 A 在全局作用域内定义了变量 foo,而脚本 B 在当前作用域内定义变量 foo。

再次强调,上面的效果完全不同,不使用 var 声明变量将会导致隐式的全局变量产生。

在函数 test 内不使用 var 关键字声明 foo 变量将会覆盖外部的同名变量。 起初这看起来并不是大问题,但是当有成千上万行代码时,不使用 var 声明变量将会带来难以跟踪的 BUG。

外部循环在第一次调用 subLoop 之后就会终止,因为 subLoop 覆盖了全局变量 i。 在第二个 for 循环中使用 var 声明变量可以避免这种错误。 声明变量时绝对不要遗漏 var 关键字,除非这就是期望的影响外部作用域的行为。

局部变量

Java 中局部变量只可能通过两种方式声明,一个是作为函数参数,另一个是通过 var 关键字声明。

foo和 i 是函数 test 内的局部变量,而对 bar 的赋值将会覆盖全局作用域内的同名变量。

变量声明提升(Hoisting)

Java 会提升变量声明。这意味着 var 表达式和 function 声明都将会被提升到当前作用域的顶部。

上面代码在运行之前将会被转化。Java 将会把 var 表达式和 function声明提升到当前作用域的顶部。

没有块级作用域不仅导致 var 表达式被从循环内移到外部,而且使一些 if 表达式更难看懂。

在原来代码中,if 表达式看起来修改了全局变量 goo,实际上在提升规则被应用后,却是在修改局部变量。

想要学习web前端的同学,可以参考成都web前端培训班提供的学习大纲;

如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常 ReferenceError。

实际上,上面的代码正常运行,因为 var 表达式会被提升到全局作用域的顶部。

注意:在 Nettuts+ 网站有一篇介绍 hoisting 的文章,其中的代码很有启发性。

名称解析顺序

Java 中的所有作用域,包括全局作用域,都有一个特别的名称 this 指向当前对象。

函数作用域内也有默认的变量 arguments,其中包含了传递到函数中的参数。

比如,当访问函数内的 foo 变量时,Java 会按照下面顺序查找:

  1. 当前作用域内是否有 var foo 的定义。
  2. 函数形式参数是否有使用 foo 名称的。
  3. 函数自身是否叫做 foo。
  4. 回溯到上一级作用域,然后从 #1 重新开始。

命名空间

只有一个全局作用域导致的常见错误是命名冲突。在 Java中,这可以通过 匿名包装器 轻松解决。

匿名函数被认为是 表达式;因此为了可调用性,它们首先会被执行。

有一些其他的调用函数表达式的方法,比如下面的两种方式语法不同,但是效果一模一样。

结论

推荐使用匿名包装器(也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突, 而且有利于程序的模块化。

另外,使用全局变量被认为是不好的习惯。这样的代码容易产生错误并且维护成本较高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值