美文网首页
作用域链

作用域链

作者: Mavericker | 来源:发表于2018-06-07 04:11 被阅读0次

由于比较复杂又很重要,所以感觉作用域链需要单独拿出来写一篇文章。感觉这篇文章真的讲的超级通俗易懂。

  1. 执行环境
    每个函数都有自己的执行环境。当执行流进入一个函数时(即调用该函数),函数的环境就会被推入一个环境栈中。而在函数执行之后,将其环境弹出栈,把控制权返回给之前的执行环境。全局执行环境是最外围的一个执行环境。全局执行环境被认为是window对象,全局执行环境直到应用程序退出--例如关闭网页或浏览器---时才会被销毁。举个例子:

          var scope = "global"; 
          function fn1(){
             return scope; 
          }
          function fn2(){
             return scope;
          }
          fn1();
          fn2();
    

    上面代码执行情况演示:

    执行函数例子

  2. this的意义:
    全局函数中(函数声明提升),this等于window;函数作为某个对象的方法调用时,指代那个对象。(可以简单看成this就是指向所在函数作用域的上一级,全局函数的上一级是window,函数的上一级是对象,可以这么简化理解),以一道面试题举个例子:

        var a=1;
     function test(){
         alert(a); //同第一题显示为undefined
         a=2;     //这里其实还有var  a,而且是全局变量,声明会被提升到最顶端但不会连同a=2一起提升,js在预编译阶段,会忽略重复的声明,然后在运行阶段赋值;
         alert(this.a); //因为this在全局函数指window所以这里的说的是window下的a所以结果为1
         this.a=4;     //改变window下的a值1的语句
         var a=3;      //局部变量a的值为3 覆盖前面局部变量
         alert(a)       //在局部域里输出当然只能是a=3
     }
     test();
     alert(a);     //由于window下的a值变为4所以此输出语句为a=4
    

    答案输出依次为:undefined 1 3 4。

    完整代码等价于:

        var a;
        var a=1;
     function test(){
         alert(a);
         a=2;
         alert(this.a);
         this.a=4
         var a=3
         alert(a)
            }
     test();
            alert(a);
    
  1. 作用域链
    当某个函数第一次被调用时,就会创建一个执行环境(execution context)以及相应的作用域链,并把作用域链赋值给一个特殊的内部属性([scope])。然后使用this,arguments(arguments在全局环境中不存在)和其他命名参数的值来初始化函数的活动对象(activation object)。当前执行环境的变量对象始终在作用域链的第0位。

    每个执行环境都有一个与之关联的作用域链,当解析器进入执行环境时被定义,作用域链是一个对象列表,用来检索各个变量对象中的变量和函数,这样可以保证执行环境有权访问哪些变量和函数,举个栗子。

    var a='123';
    function testFn(b){
      var c='abc';
      
      function testFn2(){
        var d='efg';
        alert(a);
      }
      
      testFn2();
    }
      
    testFn(10);
    

    testFn2内未声明变量a,为什么testFn2能调用全局变量a?整个过程是怎么发生的呢?请看下图。

testFn1作用域链

当解析器进入全局执行环境时,调用变量和函数时只在Global对象中查找。

当解析器进入testFn函数执行环境时,函数内部属性[[scope]]中首先填入Global对象,然后将testFn活动对象添加到Global对象之前,形成一个作用域链。

testFn2作用域链

​ 当解析器进入testFn2函数执行环境时,函数内部属性[[scope]]首先填入父级的作用域链,然后再将当前的testFn2活动对象添加到作用域链的前端,形成一个新的作用域链。

​ testFn2调用变量a时,首先在当前的testFn2活动对象中查找,如果没有找到就顺着作用域链向上,在testFn活动对象中查找变量a,如果没
有找到再顺着作用域链向上查找,直到在Global对象中找到为止,否则报所以函数内部可以调用外部环境的变量,外部环境不能调用函数内
部的变量,这就是作用域特性的原理。

相关文章

  • 作用域链和闭包

    在谈作用域链之前先说一下与作用域链关系紧密的执行环境和作用域。 作用域:作用域指的是变量的适用范围。 作用域链:作...

  • 作用域链

    作用域链 把多个作用域串起来便形成了作用域链;每个函数在初始化完成之后就拥有了各自的作用域链,但此时的作用域链中并...

  • web性能实践

    一. 作用域 前面我们了解作用域概念的以及作用域链是如何运作的。 随着作用域链中的作用域数量的增加,访问当前作用域...

  • JS_0: 执行环境和作用域链

    JavaScript,目前对于执行环境和作用域链的理解 什么是作用域链? 要讲作用域链就得先讲执行环境。 每个函数...

  • js 总结七07-19

    作用域 全局 局部 作用域链 闭包

  • 作用域和闭包

    作用域链 (据我所知)所有的编程语言都存在作用域链。整个代码存在全局作用域、函数作用以及块级作用域。 上述代码将会...

  • 2023-01-12

    变量提升调用栈块级作用域作用域链和闭包 闭包 => 作用域链(词法作用域) => 调用栈(栈溢出) => 上下文...

  • JavaScript 作用域链与闭包

    作用域链与闭包 了解作用域链之前需要先了解下作用域是什么。 作用域 几乎所有的语言都有作用域的概念。这是因为它们都...

  • 作用域/作用域链 闭包及其使用

    一、作用域、作用域链 作用域(scope) 浅显的理解: 作用域就是变量的可用范围(scope) 为什么要有作用域...

  • 作用域链

    作用域链(scope chain) 理解: 作用域链决定了哪些数据能被函数访问。当一个函数创建后,它的作用域链会被...

网友评论

      本文标题:作用域链

      本文链接:https://www.haomeiwen.com/subject/szlwsftx.html