javascript--12---作用域

作用域

  1. 什么是作用域
  • 作用: 对代码的一个读写操作
  • 域:空间 范围 js能实现的一个范围
<script>
    console.log(a);
    var a =1;
  
</script>

结果是undefined
没有声明为什么会报undefined? 首先预解析 找到a 为undefined 执行代码 =改变变量的值 但是console在等号之前 所以结果是 undefined

<script>
    a =1;
    console.log(a);
</script>

为什么没有声明却能打印出1?

  • 如果 在script没有声明 直接赋值 也能行
<script>
    console.log(a);
    a =1;
</script>

直接报错
为啥是报错? 预解析 没找到a 没有var 在console.log之前 既没有声明 也没有赋值 所以报错 后面的a=1相当于没有

<script>
   var a=1;
   console.log(window.a);
</script>

结果是1 window是script标签中最大的一个对象

  • 平时在script 中var的时候 其实是在最大的window上加了一个属性
<script>
   a=1;
   console.log(window.a);
</script>

结果是1

  • 没有var也会自动在window上加一个属性 这是系统在找不到声明的时候 自动加的

解释器

js是一种直译式脚本语言

  1. 解释器:在浏览器内核中有一个解释器 看到script标签 就直接撸起袖子干 没有长期的准备
  2. 解释器在读取js代码的时候 也至少分为两步
  • 找一些东西 根据关键字 去查找 var(变量声明) function(函数声明) 参数
    找到变量声明之后 不去读取赋值 而是直接给一个undefined值

    找到函数声明之后不会执行函数  而是把函数的内容当作一块直接存起来
      比如  a:function(){}
  • 解释代码 先找到我们的 预解析找到的变量 如果有能改变变量值的运算:+ — ++ -- */% 修改了这个先找到的undefined/function(){}

<script>
   alert(a);//结果是function a(){alert(3)}
   var a=1;
   alert(a);//结果是1
   function a() {
       alert(2);
   }
   alert(a);//结果是1
   var a=3;
   alert(a);//结果是3
   function a() {
       alert(3);
   }
   alert(a);//结果是3
   a();//报错
</script>
  1. 预解析
  • a :undefined 如果预解析过程中 函数名和变量重名了 函数会把变量无情覆盖
  • a :function{alert(2)}
  • 如果预解析中 有重名函数 后者会把前者覆盖
  • a :function{alert(3)}
  1. 执行阶段
  • 第一个alert 结果是打印函数体function{alert(3)}
  • 修改a=1,第二个alert 结果是打印1
  • function只在预解析会用到 跳过function 第三个alert 结果是打印1
  • 修改a=3,第四个alert 结果是打印3
  • 跳过function 第五个alert 结果是打印3
  • a=3 3();是啥哦 会报错

全局作用域 和 局部作用域

全局作用域

  1. 最大的作用域是 script标签之间 全局中最大的对象是 window window是最大的作用域 但是script是分别解释的 代码自上而下执行 script全部解读完之后 window还是最大的对象 在引入代码的时候一定要注意引入顺序 因为script是分别解释的
<script>
  alert(a);
</script>
<script>
    var a =1;
</script>

结果会报错 代码自上而下执行 没有解析下面的var a=1;

<script>
   var a =1;
</script>
<script>
  alert(a);
</script>

结果是1; 会把a=1存起来 执行到下一个script 会在小仓库里找a

局部作用域

  1. 函数内部也是一个空间 函数构建的空间 可以被看作一个局部作用域
  2. 如果局部作用域的预解析的空间 没有找到 那么我的代码执行 会从上一级作用域寻找 上一级作用域不能在下一级作用域寻找
  3. 预解析的空间 :AO ----活动对象
<script>
  var a =1;
  function fn1() {
      alert(a);
      var a =2;
  }
  fn1();
  alert(a);
</script>

第一个结果是 undefined 第二个结果是 1

  1. 预解析 AO分析
  • a:undefined fn1{}
  1. 代码执行 a=1
  • fn1执行 :进入函数内部 1预解析 a:undefined 2 执行 alert(a) a=2
  • alert(a) 所以结果是先 undefined 后1
<script>
  var a =1;
  function fn1() {
      alert(a);
  }
  fn1();
  alert(a);
</script>

结果是1 1

  1. 预解析
  • a:undefined fn1{}
  1. 代码执行 a=1
  • fn1执行 :进入函数内部 1预解析 预解析是空 2 执行 alert(a) 跳出函数在全局中寻找a a=1 所以结果是1
  • alert(a) 所以结果是先 1 后1

参数

  1. 形参 相当于隐式声明 在AO上为undefined
  2. 实参 会在AO分析时候 给形参一个初始值
<script>
  var a =1;
  function fn1(a) {
      alert(a);
      a =2;
  }
  fn1();
  alert(a);
</script>
  1. 预解析
  • a:undefined fn1{}
  1. 代码执行 a=1
  • fn1执行 :进入函数内部 1预解析 形参相当于声明变量a:undefined 2 执行 alert(a)所以结果是undefined 之后赋值a=2;
  • alert(a) 所以结果是先 undefined 后1
<script>
  var a =1;
  function fn1(a) {
      alert(a);
      a =2;
      alert(a);
  }
  fn1(a);
  alert(a);
</script>
  1. 预解析
  • a:undefined fn1{}
  1. 代码执行 a=1
  • fn1执行 :进入函数内部 1预解析 实参传值 a=1 2 执行 alert(a)所以结果是1 之后赋值a=2;
  • alert(a) 所以结果是先 1 后2 再 1
<script>
   var a =1;
   function f1() {
    alert(a);
    a=2;
   }
   f1();
   alert(a);
</script>

结果是 1 2

<script>
  var age =99;
  function t(age) {
      alert(age);
  }
  t(5);
  t();
</script>
  1. 预解析
  • age:undefined t:function{}
  1. 代码执行 age=99
  • t(5)执行 :进入函数内部 1预解析 实参传值 age=5 2 执行 alert(age)所以结果是5
  • t()执行 进入函数 1 预解析 形参相当于声明变量a:undefined alert(age) 所以结果是先5 后undefined
<script>
  function t2(green) {
      alert(green);
      function green() {

      }
      green="hello";
      alert(green);
  }
  t2(null);
  1. 预解析
  • green:null 进入函数内部 有一个函数声明 会覆盖 green=function green() {}
  1. 代码执行 alert(green) 结果是 function
  • green:hello
  • alert(green) 结果是hello 所以 第一个是函数体 第二个是hello
<script>
  function a(b) {
      alert(b);
      function b() {
          alert(b);
      }
      b();
  }
  a(1);
</script>
  1. 预解析
  • b=1 进入函数内部 有一个函数声明 会覆盖 b=function b(){}
  1. 代码执行 alert(b) 结果是 function
  • b() 执行 进入b(){}内部 并没有 var b 跳出当前函数 找到b为function 所以alert(b) 是函数本身 结果两个都是函数本身
<script>
  function a(b) {
      alert(b);
      b=function(){
          alert(b);
      }
      b();
  }
  a(1);
</script>
  1. 预解析
  • b=1 进入函数内部 没有函数声明 变量声明
  • 代码执行 alert(b) 结果是1
  • 赋值b=function(){}
  1. b()执行 进入函数体内部 没有var b 跳出 b=function 结果是function 所以第一个是1 第二个是函数本身

作用域分析

  1. 先看看有没有参数 实参会把形参初始化 如果只有形参 那么形参为undefined
  2. 再看看有没有变量声明 函数会把同名变量覆盖 包括实参

jquery部分代码

  1. 传window是为了性能
  2. 不穿undefined 是为了函数内部不被污染
<script>
  (function (window,undefined) {
      function(){
          function(){
              function(){
                  window.document.getElementById()
              }
          }
      }
  })(window);
</script>

如果函数内部没有 window 那么document.getElementById()要执行 会跳出这个函数 当层数太多 性能就会很低 所以会实参会传一个window到函数内部 形参undefined 初始值就是undefined 不用实参传 再低版本的ie中 undefined可以被赋值 如果在函数外部 定义undefined=1 实参传undefined 那么函数内部undefined 就会被污染为1 如果函数内部做判断 if(a==undefined)就不可以

作用域链

内层作用域在寻找变量时候未找到 会沿着作用域上的AO 向上寻找 直到全局

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章