关于JS作用域及作用域链解析

172 阅读3分钟

作用域

概念

作用域就是变量的可用范围(scope)

为什么要有作用域

目的是防止不同范围的变量之间互相干扰

有几种作用域

  • 全局作用域
    • 概念:不属于任何函数的外部范围称为全局作用域;保存在全局作用域的变量称为全局变量
    • 优点: 可反复使用
    • 缺点:全局污染
  • 函数作用域
    • 一个函数内的范围称为函数作用域; 保存在函数作用域内的变量称为局部变量
    • 优点: 不会被污染
    • 缺点: 无法反复使用
    • 特例:形参变量也是函数内的局部变量; fucntion f(y){ // y 为局部变量} 举例:
    var x = 1; // 全局作用域
    function f(){
        var y = 2; // 局部作用域
    }

强调: 只有函数的{},才能形成作用域;

  • 不是所有{}都能形成作用域。
  • 也不是所有{}内的数据都能是局部变量
  • 举例:
    • 对象的{},就不是作用域!
    • 对象中的属性,也不是局部变量;
var lilei={
        sname: “Li Lei”,
        intr:function(){
        console.log(“我是${this.sname}”) // 为什么这里必须加this?
        // 因为:都是因为对象的{}不是作用域,对象中的属性不是局部变量。
        }
}

强调: JS中没有块级作用域

  • 函数{}之外的其余{},都不是作用域
  • 拦不住内部的变量超出{}的范围影响外部程序
  • 举例:
    console.log(a); //不报错, undefined
    if(false){ //不是作用域,拦不住变量被声明提前
    var a=10;
    }
    console.log(a); // 10

作用域链

概念:

一个函数可用的所有作用域串联起来,就行成了当前函数的作用域链

解析:其实每个函数在定义时,就已经规划好了自己专属的一个查找变量 的路线图,称为作用域链。

如下图:看看什么是作用域链;

image.png 特殊: 给从未声明过的变量赋值
image.png 总结:

Js中只有两种局部变量:①:函数内var出来的 ②:函数的形参变量;
看不见var,形参里也没有就不是局部变量。

举例三道题用来理解,局部变量、全局变量以及作用域链

题一:

   var a = 10 、、 全局变量
   function fun(){
       var a= 100; // 局部变量
       a++
       console.log(a) // 101
   }
   fun();
   console.log(a)  // 10

题二:

   var a = 10  // 全局变量
   function fun(){
       a= 100;  // 给全局变量赋值
       a++
       console.log(a) // 101
   }
   fun();
   console.log(a)  // 101

题三:

var a = 10 // 全局变量
   function fun(a){
       a++; // 传入的a为局部变量,给a做运算
       console.log(a) // 11
   }
   fun(a);
   console.log(a)  // 10

作用域的本质:作用域和作用域链都是对象结构

image.png

总结:全局作用域其实是window对象;所有全局变量和全局函数都是window 对象的成员

补充:函数作用域 -- 又叫:活动的对象(ActivedObject) --简称, AO。

概念:其实是js引擎在调用函数时才临时创建的一个作用域对象。其中保存函数的局部变量。而函数调用完,函数作用域对象就释放了。

直观对比:

函数作用域创建: image.png 函数作用域销毁:函数执行完之后,立即销毁,所以局部变量不可重用;

image.png