转载

理解 Javascript 中变量的作用域

Javascript 这门语言与其他的大部分语言相比,有很多特殊性,这是很多人喜欢它或者讨厌它的原因。其中变量的作用域问题,对很多初学者来说就是一个又一个「坑」。

变量的作用域在编程技能中算是一个基本概念,而在 Javascript 中,这一基本概念往往挑战者初学者的常识。

基本的变量作用域

先上例子:

javascriptvar scope = 'global'; function checkScope(){  var scope = 'local';  console.log(scope); // local } checkScope(); console.log(scope); // global  

上面的例子中,声明了全局变量 scope 和函数体内的局部变量 scope 。在函数体内部,局部变量的优先级比通明的全局变量要高,如果一个局部变量的名字与一个全局变量相同,那么,在 声明局部变量的函数体范围内 ,局部变量将覆盖同名的全局变量。

下面再看一个例子:

javascriptscope = 'global'; function checkScope(){  scope = 'local';   console.log(scope); // local  myScope = 'local';  console.log(myScope); // local } checkScope(); console.log(scope); // local console.log(myScope); // local  

对于初学者来说,可能会有两个疑问:为什么在函数体外, scope 的值也变成了 local ?为什么在函数体外可以访问 myScope 变量?

这两个问题都源于一个特性。在全局作用域中声明变量可以省略 var 关键字,但是如果在函数体内声明变量时不使用 var 关键字,就会发生上面的现象。首先,函数体内的第一行语句,把全局变量中的 scope 变量的值改变了。而在声明 myScope 变量时,由于没有使用 var 关键字,Javascript 就会在全局范围内声明这个变量。因此,在声明局部变量时使用 var 关键字是个很好的习惯。

在 Javascript 中,没有「块级作用域」一说

在 C 或者 Java 等语言中, iffor 等语句块内可以包含自己的局部变量,这些变量的作用域是这些语句的语句块,而在 Javascript 中,不存在「块级作用域」的说法。

看下面的例子:

javascriptfunction checkScope(obj){  var i = 0;  if (typeof obj == 'object') {   var j = 0;   for (var k = 0; k < 10; k++) {    console.log(k);   }   console.log(k);  }  console.log(j); } checkScope(new Object());  

在上面的例子中,每一条控制台输出语句都能输出正确的值,这是因为,由于 Javascript 中不存在块级作用域,因此, 函数中声明的所有变量,无论是在哪里声明的,在整个函数中它们都是有定义的

如果要更加强调上文中 函数中声明的所有变量,无论是在哪里声明的,在整个函数中它们都是有定义的 这句话,那么还可以在后面跟一句话: 函数中声明的所有变量,无论是在哪里声明的,在整个函数中它们都是有定义的,即使是在声明之前 。对于这句话,有个经典的困扰初学者的「坑」。

javascriptvar a = 2; function test(){     console.log(a);     var a = 10; } test(); 

上面的例子中,控制台输出变量 a 的值为 undefined ,既不是全局变量 a 的值 2 ,也不是局部变量 a 的值 10 。首先, 局部变量在整个函数体内都是有定义的 ,因此,局部变量 a 会在函数体内覆盖全局变量 a ,而在函数体内, var 语句之前,它是不会被初始化的 。如果要读取一个未被初始化的变量,将会得到一个默认值 undefined

所以,上面示例中的代码与下面的代码时等价的:

javascriptvar a = 2; function test(){  var a;  console.log(a);  a = 10; } test();  

可见,把所有的函数声明集合起来放在函数的开头是个良好的习惯。

未完待续……

正文到此结束
Loading...