一、  什么是作用域


作用域,即 变量起作用的区域。



变量定义后,可以在哪个范围内使用该变量



二、两种作用域



     1.词法作用域、



     2.块级作用域



块级作用域:



用一个块(代码块)结构限制变量的访问区域。



即,块内的每一段代码都有各自的作用域,变量在声明它们的代码段之外是不可见的。



代表语言: C 语言( C系,如:Java、Object-C、C#)



 



案例



 


for(var i = 0; i < 10; i++) { 
   
     console.log(i); 
   
 }console.log(i);//10


 


 



三、词法作用域



     



概念:变量的作用范围, 在书写代码的时候就已经决定, 与运行时无关。



            函数在定义它们的作用域中运行,而不是在调用它们的作用域里运行



            JavaScript中只有函数才能形成作用域,因此也叫做函数作用域



案例:


// 1 
    
 function foo() { 
    
     var num = 123; 
    
   

         console.log(num);  //  
   
 
   

     } 
    
 foo(); 
    
   

     console.log(num); //



变量提升后:



function foo(){ 
   
 
   

          var num; 
   
 
   

          num = 123; 
   
 
   

          console.log(num); =>123 
   
 
   

     } 
   
 
   

     foo(); 
   
 
   

     console.log(num);//先去当前作用域里面找,看有没有声明;因为是全局环境下,所以没有找到num,程序会报错



java Runnable使用域外变量_javascript

 


// 2 
    
 var scope = "global"; 
    
 function foo() { 
    
     console.log(scope); // 
    
     var scope = "local"; 
    
     console.log(scope); // 
    
 } 
    
   

     foo();


变量提升后:


var scope; 
   
 
   

         scope = "global"; 
   
 
   

     function foo(){ 
   
 
   

          var scope; 
   
 
   

          console.log(scope); =>先去当前作用域找变量的声明,如果没有则向上一级找,本例中,当前作用域中有声明,但是在该位置没有赋值,所以输出undefined 
   
 
   

          scope = "local"; 
   
 
   

        console.log(scope); =>先去当前作用域找变量的声明,如果没有则向上一级找,有声明,并且有赋值,所以输出local 
   
 
   

     } 
   
 
   

     foo();




java Runnable使用域外变量_java Runnable使用域外变量_02


// 3 
   
    

     // 声明的变量都作为 window 全局对象的属性存在! 
   
    

     if("a" in window){ 
   
    

         var a = 10; =>因为这里并不是一个作用域,所以变量会向上提升至全局环境, 
   
    

     } 
   
    

     alert(a); // ?


变量提升后

var a ; 
   
    

     if('a' in window){ 
   
    

          a = 10; 
   
    

     } 
   
    

     alert(a); =>10;


java Runnable使用域外变量_java Runnable使用域外变量_03


if(!"a" in window){ 
    
     var a = 10;     
 }     

 alert(a); // ?


 

java Runnable使用域外变量_java Runnable使用域外变量_04

 

// 4 
    
 var foo = 1;     
 function bar() {     
     if(!foo) {     
         var foo = 10;     
     }     
     alert(foo); //     
 }        

     bar();


 


变量提升后


var foo; 
   
    

     foo = 1; 
   
    

     function bar(){ 
   
    

        var foo; 
   
    

        if(!foo){     =>foo声明未赋值,为undefined,隐式转换为false ,经过非运算符之后为true 
   
    

           foo = 10; 
   
    

         } 
   
    

        console.log(foo); =>因为上面条件为真,程序进入判断语句中,foo为10;所以最后输出10 
   
    

     } 
   
    

     bar();


 


四、变量提升和函数提升(hoisting)


  • JavaScript的执行过程
JS运行的两个步骤:解析和执行
1 预解析(不是在执行代码)。 将所有的声明都加载到内存中,也就是:告诉解释器有什么东西了
2 一步一步的执行代码, 按照从上往下的顺序
  • 变量提升的是:变量的声明
  • 函数提升的是:整个函数

案例变式:


2 变式
 if("b" in window) {
     var a = 10;
 }     

      alert(a); // ? undefined 
    
     

      变量提升后 
    
     

      var a ; 
    
     

      if('b' in window){ 
    
     

           var a = 10; 
    
     

      } 
    
     

      console.log(a);


java Runnable使用域外变量_javascript_05

 


3 变式

if(true) {
     function f() { alert("true"); }
 } else {
     function f() { alert("false"); }
 }
 f();// ? 不确定,会根据不同浏览器实现不同


4 变式

var f; 
    
     
      if(true) {     
     

          f = function () { alert("true"); } 
    
     
      } else {     
     

          f = function () { alert("false"); } 
    
     
      }     
     

      f();// true