五句话搞定JavaScript作用域

原文:http://www.cnblogs.com/wupeiqi/p/5649402.html

此文针对ES,不涉及ES2015(ES6)

一、“JavaScript中无块级作用域”

  • 大括号不是一个作用域。
function Main() {
   if(true) {
      var name = 'JAMES';
   }
   console.log(name);   // JAMES
}

补充:标题之所以添加了引号是因为ES6中引入了let关键字 用于指定变量属于块级作用域

二、JavaScript采用函数作用域

  • 在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。
function Main() {
   var innerValue = 'ABC';
}
Main();
console.log(innerValue);   // Uncaught ReferenceError: innerValue is not defined

三、 JavaScript的作用域链

  • 由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。
xo = 'five';
function Func() {
   var xo = 'six';
   function innerFunc() {
      var xo = 'seven';
      console.log(xo);
   }
   innerFunc();
}
Func();  // seven

如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量的时候就会出现顺序,对于上述示例:当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。


五句话搞定JavaScript作用域_第1张图片
image

四、JavaScript的作用域链执行前已经创建

  • JavaScript的作用域在执行前已经创建,日后再去执行时只需要按照作用域链去寻找即可。
  • 示例一
xo = 'five';
function Func() {
   var xo = 'six';
   function innerFunc() {
      console.log(xo);
   }
   return innerFunc;
}
var ret = Func();
ret();   // six

上述代码,在函数被调用之前作用域链已经存在:
全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域。
当执行ret();时,由于其代指的是innerFunc函数,此函数的作用域链在执行之前就被定义为:全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域,所以,在执行ret();时,会根据已经存在的作用域链去寻找变量。

  • 示例二
xo = 'five';
function Func() {
   var xo = 'six';
   function innerFunc() {
      console.log(xo);
   }
   xo = 'seven';
   return innerFunc;
}
var ret = Func();
ret();   // seven

上述代码和示例一的目的相同,也是强调在函数调用之前作用域链已经存在:
全局作用域 -> Func()函数作用域 -> inneFunc()函数作用域

  • 示例三
xo = 'five';
function Bar() {
   console.log(xo);
}
function Func() {
   var xo = 'six';
   return Bar;
}
var ret = Func();
ret();   //five

上述代码中,在函数被执行之前就已经创建了两条作用域链:
全局作用域 -> Bar()函数 ;全局作用域 -> Func()函数;当执行ret(),ret执行Bar函数,而Bar的作用域链已经存在,就会根据Bar函数的作用域链去寻找。

五、声明提前

  • 在JavaScript中如果不创建变量,直接去使用则报错:
console.log(xxoo);
 // Uncaught ReferenceError: xxoo is not defined
  • 如果创建变量而不赋值,则为undefined:
var xxoo;
console.log(xxoo);
// undefined
  • 在函数内如果这么写:
function Foo() {
   console.log(xo);
   var xo = 'seven';
   console.log(xo);
}
Foo();
// undefined
// seven

上述代码,不报错而是输出undefined,其原因是:JavaScript的函数在执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述示例三中,函数在"预编译"时,已经执行了var xo;所以上述的代码输出是undefined。

你可能感兴趣的:(五句话搞定JavaScript作用域)