Javascript面向对象编程指南(三)

变量的作用域

这是一个至关重要的为题。特别是当我们从别的语言转向JS的时,必须要明白这一点,即在Javascript中,变量的定义并不是以代码块作为作用域的,而是以函数作为作用域的。也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的。而如果变量是定义在if或者for这样的代码块中的,它在代码块以外是可见的。另外,在Javascript中,术语“全局变量”指的是定义在所有函数之外的变量(也就是定义在全局代码中的变量),与之相对的是“局部变量”,所指的则是在某个函数中定义的变量。其中,函数内的代码可以像访问自己的局部变量那样访问全局变量,反之,则不行。

下面来看一个具体演示,请注意两点:

  • 函数f()可以访问变量global;
  • 在函数f()以外,变量local是不存在的。
var global = 1;
function f() {
  var local = 2;
  global ++;
  return global;
}

f();  // 2
f();  // 3
local;  // local is not defined

这里还有一点很重要,如果我们声明一个变量时没有使用var语句,该变量就会被默认为全局变量。

最佳实践

  • 尽量将全局变量的数量降到最低,以避免命名冲突,因为如果有两个人在同一脚本的不同函数中使用了相同的全局变量名,就很容易到很容易导致不可预测的结果喝难以观察的bug
  • 最好总是使用var语句来声明变量
  • 可以考虑使用“单一var”模式,即,仅在函数体内的第一行使用一个var来定义这个作用域中所有需要的变量。这样一来,我们就能很轻松地找到相关变量的定义,并且在很大程度上避免了不小心污染全局变量的情况。
变量提升

下面我们来看一个很有趣的例子,它显示了关于局部和全局作用域的另一个重要问题。

var a = 123;
function f(){
  alert(a);
  var a = 1;
  alert(a);
};
f();

你可能会想当然的认为alert()第一次显示的是123(也就是全局变量a的值),而第二次显示的是1(即局部变量a)。但事实上并非如此,第一个alert()实际上显示的是undefined,这是应为函数域始终优先于全局域,所以局部变量a会覆盖掉所有与它同名的全局变量,尽管在alert()第一次被调用时,a还没有被正式定义(即该值为undefined),但该变量本身已经存在于本地空间了。这种特殊的现象叫做提升

也就是说,当Javascript的执行过程进入新的函数时,这个函数内被声明的变量都会被移动(或者说被提升)到函数最开始的地方。这个概念很重要,必须牢记。另外需要注意的是,被提升的只有变量的声明,这意味着,只有函数体内声明的这些变量在该函数执行开始时就存在,而与之相关的赋值操作并不会被提升,它还在原来的位置上。譬如在上面的例子中,局部变量本身被提升到了函数开始处,但并没有在开始处就被赋值为1。这个例子可以等价为:

var a = 123;
function f() {
  var a;
  alert(a);  // undefined
  var a =1;
  alert(a)  // 1
}

你可能感兴趣的:(Javascript面向对象编程指南(三))