1.作用域概述

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个 名字的可用性的代码范围就是这个名字的作用域,作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突

1.1.js作用域(es6之前)分为: 全局作用域 局部作用域

1.2.全局作用域 :整个script标签 或者是一个单独的js文件

       var num = 10 ;(这一个标签是写在全局作用域里面 这个变量名是可用的 称之为全局作用域)

1.3.局部作用域(函数作用域):在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用

 var num = 10  //全局作用域
 function fn(){
  //局部作用域
   var num = 20 ; //局部下的num和全局下的num是不冲突的因为输出的不一样
   console.log(num) //20
 }
 fn()  //切记调用
 console.log(num) // 10
 

2.变量作用域

在js中,根据作用域的不同,变量可以分为俩种:全局变量,局部变量

2.1.全局变量:在全局作用域下的变量 在全局下都可以使用(在函数外部定义的变量)(3.特殊情况注意一下:如果在函数内部,没有声明直接赋值的变量也属于全局变量)

  var num=10;
  console.log(num);//可以打印  10 
  function fn(){ //函数
    console.log(num)//也是可以打印的 10 
  }
  fn()
  console.log(aru) //4.aru is not defined   不能使用

2.2.局部变量:在局部作用域下的变量 或者可以理解为在函数内部的变量就是局部变量(在函数内部定义的变量)(注意:函数的形参也可以看做是局部变量 4.aru是一个形参)

function fun(aru){
  var num1 = 10; //1.num就是局部变量 特点就是只能在函数内部使用
  num2 = 20; //3 . 如果在函数内部,没有声明(不适用var)直接赋值的变量也属于全局变量
}
fun();
console.log(num1);  //2.num is not defined 报错  所以说外部是不能使用的
console.log(num2); //3. 20 如果在函数内部,没有声明直接赋值的变量也属于全局变量

2.3.区别:从执行效率来看全局变量和局部变量
(1)全局变量在任何一个地方都可以使用,只有浏览器关闭的时候才会销毁,比较占内存资源
(2)局部变量 当我们程序执行完毕就会销毁,比较节约内存资源

3.作用域链

3.1.只要是代码,就至少有一个作用域

var num = 10; //全局作用域

3.2.在函数内部的叫做局部作用域

var num = 10;
function fun(){  //外部函数
  var num = 20; 
  function fn(){//3.3.在fun函数里面有生成了一个fn函数   作用域里面诞生了一个新的作用域   内部函数
  console.log(num);//3.4.执行是20还是10呢 20  用链式查找决定  它会往上一级找有没有num 一层一层的找就是链式查找
   }
   fn()
}
fun()

3.3.如果函数中还有函数,那么在这个作用域中就有可以诞生一个作用域
3.4.根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链(简单理解就是就近原则,谁离的近就执行谁)

案例1:

function f1(){   //1  可以称为0级链
  var num = 123;    //2  可以称为1级链
  function f2(){    //2  可以称为1级链
     console.log(num);    //3 可以称为2级链       123
  }  
  f2()
}
var num = 456;  //1 可以称为0级链
f1();

案例2:

 var a = 1;
 function fn1(){
    var a = 2;
    var b = '22';
    fn2();
    function fn2(){
       var a = 3;
       fn3();
       function fn3(){
          var a = 4;
          console.log(a);   //4
          console.log(b);   //22
        }
    }
  }
 fn1();     

4.预解析

.1问

 console.log(num) //num is not defined   没有声明没有赋值

.2问

console.log(num) //undefined   坑1
var num = 10; 

~ 相当于执行了以下代码

var num;   //把var提升到当前作用域的最前面  但是不提升赋值(num = 10)
console.log(num);  //只声明不赋值  所以输出就是 undefined
num = 10;

.3问


//fn(); 
function fn(){    
  console.log(11)  //fn()前后调用都是11  
}
fn();

.4问

//fun()  //var fun变量是不可以当函数使用的   function
var fun  = function(){   
  console.log(22) //22  
}
fun() 

~相当于执行了以下代码

var fun;     //把var提升到当前作用域的最前面  声明了一个变量没有给值
fun();      
fun = function(){   //函数表达式
  console.log(22) //22  
}
//fun(); //当它赋完值以后它就有函数了 就可以调用了(调用是写在函数表达式声明的下面)

什么是预解析

1.js代码是由浏览器中的js解析器来执行的,js解析器在运行js代码的时候分为俩步:预解析和代码执行

(1).预解析 : js引擎会把js 里面所有的var 还有function 提升到当前作用域的最前面
(2).代码执行 : 按照代码的书写顺序从上往下执行 

2.预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)

 (1).变量提升:就是把所有的变量声明提升到当前的作用域最前面,不提升赋值操作
 (2).函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数(函数表达式 调用必须写在函数表达式下面)


案例1:

  var num = 10;
  fun();
  function fun(){
    console.log(num);    //undefined
    var num = 20;
  }

~相当于执行了以下代码

var num;  //1.先把var进行提升 提升到当前作用域最前面  
function fun(){  //2.var num变量  当前作用域是 function fun函数内部的就没有  这里把这个大的函数要提升拿过来
    var num  //4.把变量提升到当前作用域的最前面  
    console.log(num);
    num = 20;
 }  
 num =10;  //3.依次写就行 正常代码
 fun();

按照作用域链执行 首先有个var num 然后执行函数function 函数没有调用不执行 略过 往下走 num存了一个10 往下走 fun()调用函数在回头调用函数往function里面走 调用函数之后里面有个var num 再看console.log(num); 就近原则 那就是var num离得最近 var num只有num没有值 所以就是undefined

正确这样写

    var num = 10;
    function fun(){
       var num = 20;
       console.log(num)
    }
    fun()

案例2:

var num = 10;
function fn(){
   console.log('1',num)  //undefined
   var num =20;
   console.log('2',num)  //20
}
fn()

~相当于执行了以下代码

var num;
function fn(){
   var num
   console.log('1',num)  //undefined
   num =20;
   console.log('2',num)  //20
}
num =10;
fn();

案例3:

var a =18
f1();
function f1(){
  var b = 9
  console.log(a)//undefined
  console.log(b)//9
  var a = '123'
}

~相当于执行了以下代码

var a;
function f1(){
  var b;
  var a;
  b = 9
  console.log(a)  //undefined
  console.log(b)  //9
  a = '123'
}
f1();

案例4:

f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
   var a = b = c = 9;
   console.log(a);
   console.log(b);
   console.log(c);
 }

~相当于执行了以下代码

function f1(){            //1.因为没有变量所以就把函数提到前面   2.先打印函数里面的  因为函数提升到前面了
    var a=9;b=9;c=9    //相当于 var a=9;b=9;c=9   b,c 直接赋值没有var声明当全局变量看(赋值了没有声明就是全局变量)
    console.log(a); //9
    console.log(b); //9
    console.log(c); //9
 }
f1();   //1.依次排过来
console.log(c);//9  因为b,c是全局变量任何地方都可以使用的
console.log(b);//9  因为b,c是全局变量任何地方都可以使用的
console.log(a);//defined  因为a是局部变量 外面是不可以调用的


张东红
1 声望1 粉丝

« 上一篇
动画1