您好,欢迎来到华佗养生网。
搜索
您的当前位置:首页JavaScript — 变量提升与函数提升、执行上下文、作用域

JavaScript — 变量提升与函数提升、执行上下文、作用域

来源:华佗养生网

 


一、变量提升与函数提升

1.变量声明提升

        通过var定义(声明)的变量,在定义语句之前就可以访问到

        值:undefined

2.函数声明提升

        通过function声明的函数,在之前就可以直接调用。必须使用函数声明的方式

        值:函数定义(对象)

3.问题:变量提升和函数提升是如何产生的?

        1、在js中js引擎会优先解析var变量和function定义!在预解析完成后从上到下逐步进行!

        2、解析var变量时,会把值存储在“执行环境”中,而不会去赋值,值是存储作用!例如:

alert(a); var a = 2; 这时会输出undifiend,意思是没有被初始化没有被赋值!这并不是没有被定义,错误了的意思!

        3、在解析function时会把函数整体定义,这也就解释了为什么在function定义函数时为什么可以先调用后声明了!其实表面上看是先调用了,其实在内部机制中第一步实行的是把以function方式定义的函数先声明了(预处理)

    console.log(b); //undefined 变量提升
    fn2();  //“fn2()”可调用 函数提升
    fn3();  //不能 变量提升
    var b=3;
    function fn2(){
        console.log("fn2()");
    }
    var fn3 = function(){
        console.log("fn3()");
    }

 

二、执行上下文

1.代码分类

    *全局代码

    *函数(局部)代码

 

2.全局执行上下文

    *在执行全局代码前将window确定为全局执行上下文

    *对全局数据进行预处理

        *var定义的全局变量==>undefined,添加为window属性

        *function声明的全局函数 ==> 赋值(fun),添加为window的方法

        *this==>赋值(window)

    *开始执行全局代码

    //全局执行上下文
    console.log(a1,window.a1);  //undefined undefined
    a2()    //"a2()"
    console.log(this);  //Window
    var a1 = 3;
    function a2(){
        console.log("a2()");
    }

 

3.函数执行上下文

        *在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象

        *对局部数据进行预处理

            *形参变量==>赋值(实参)==>添加为执行上下文的属性

            arguments==>赋值(实参列表),添加为执行上下文的属性

            var定义的局部变量==>undefined,添加为执行上下文的属性

            function声明的函数 ==> 赋值(fun),添加为执行上下文的方法

            this ==> 赋值(调用函数的对象)

        开始执行函数体代码

    //函数执行上下文
    function fn(a1){
        console.log(a1);    //5
        console.log(a2);    //undefined
        a3()    //"a3()"
        console.log(this);  //window
        console.log(arguments); //伪数组(5,6)
        var a2 = 3;
        function a3(){
            console.log("a3()");
        }
    }
    fn(5,6)

 

三、执行上下文栈

    1.在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象

    2.在全局执行上下文(window)确定后,将其添加到栈中(压栈)

    3.在函数执行上下文创建后,将其添加到栈中(压栈)

    4.当前函数执行完后,将栈顶的对象移除(出栈)

    5.当所有的代码执行完后,栈中只剩下window

 

let a = 'Hello World!';
function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}
function second() {
  console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');

 

四、作用域

1.理解

     就是一块“地盘”,一个代码段所在的区域

     它是静态的(相对于上下文对象),在编写代码时就确定了

2.分类

     全局作用域

     函数作用域

     没有块作用域(ES6有了)

3.作用

     隔离变量,不同作用域下同名变量不会有冲突

    JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。

    ECMAScript 6(简称ES6)中新增了块级作用域。

    块作用域由 { } 包括if语句for语句里面的{ }也属于块作用域,if语句和for语句中用var定义的变量可以在外面访问到。

    通过var定义的变量可以跨块作用域访问到,不能跨函数作用域访问到。

    var、let、const的区别

    var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。

    let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。

    const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

五、作用域与执行上下文 

1.区别1

    *全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了,而不是在函数调用时。

    *全局执行上下文环境是在全局作用域确定之后,JS代码马上执行之前创建

    *函数执行上下文是在调用函数时,函数体代码执行之前创建

 

2.区别2

    *作用域是静态的,只要函数定义好了就一直存在,且不会再变化

    *执行上下文是动态的,调用函数时创建,函数调用结束时上下文环境就会自动释放

 

3.联系

    *执行上下文(对象)是从属于所在的作用域

    *全局上下文环境从属于全局作用域

    *函数上下文环境从属于对应的函数作用域

六、作用域链

1.理解

    *多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)

    *查找多个变量时就是沿着作用域链来查找的

 

2.查找一个变量的查找规则

        1.在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入2

        2.在上一级作用域的执行上下文中查找对应的属性,如果有直接返回,否则进入3

        3.再执行2的相同操作,直到全局作用域,如果还找不到就抛出找不到的异常

 

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo7.cn 版权所有 湘ICP备2022005869号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务