JS预编译(预编译,函数声明提升问题,一篇足矣)

  • Post author:
  • Post category:其他




前言

相信学习过js的人都听说过这两句话:

  • 函数声明整体提升
  • 变量声明提升

这两句话是预编译的简化版,当然只会这两句话做项目的过程遇到一些问题时没有办法解决的,那么本篇就从原理讲这个预编译,

学完本篇保证预编译的面试题、以及项目中的bug,通通解决。



一、Js运行过程

首先我们要学习Js的运行过程,这样才会更容易理解这个预编译,我们都知道Js是单线程的解释性语言。

Js运行总共有三部:

  1. 语法分析:在运行之前先给你检测一遍你这个代码,保证你能运行
  2. 预编译:在函数执行的前一刻,会创建一个叫做执行期上下文的(AO)对象这个创建执行期上下文的过程叫做预编译。
  3. 解释执行:前两部都没问题,开始解释代码然后执行

那么第一步和第三步都很简单,第二部也是很难理解的也是我们今天的主角:

预编译



二、Js预编译

上面我们也说了,这个预编译发生在函数执行前,那么我们先来看一段代码


    function test(a,b){
        console.log(a);
        console.log(b)
        console.log(c)
        console.log(d)
        var c = 123;
        function d(){

        } 
    }
    test(1);

那么这里的a我们可能大多数人都知道是1,那么b、c、d都输出什么呢?我们预编译就是解决这类问题的。

这个a、b、c、d的值都是从这个执行期上下文(AO对象)中获取值的,那么下面我们就来看看创建这个AO对象的过程也就是预编译:

  1. 创建AO对象 Activation object (执行期上下文)作用域
  2. 找形参和变量声 明,将变量和形参名作为AO属性名 ,值为undefined
  3. 将实参和形参值统一
  4. 在函数体里面找函数声明,值赋予函数体

那么我们再来看上面的代码,这回根据上面的四部曲,是不是就简单了很多呢


//     1. 首先创建AO对象
// AO{


// }
// 2. 找形参和变量声明,将变量和形参名作为AO属性名 ,值为undefined

// AO{
// 	a:undefined,
// 	b:undefined,
// 	c:undefined,
// }
// 3. 将实参和形参值统一 我们在传入的时候传入了一个1
// AO{
// 	a:1,
// 	b:undefined,
// 	c:undefined,
// }

// 4.在函数体里面找函数声明,值赋予函数体

// AO{
// 	a:1,
// 	b:undefined,
// 	c:undefined,
// 	d:function d(){

//         } 
// }

function test(a,b){
        console.log(a);// 1
        console.log(b);// undefined
        console.log(c);// undefined
        console.log(d);// function d(){}
        var c = 123;
        function d(){

        } 
    }
    test(1);



三、练习

那么学完,下面我准备了一道小题,给大家巩固一下知识。


    function fn(a){
        console.log(a);
        var a =12;
        console.log(a);
        function a() {

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

        }
        console.log(b);

        function d(){

        }
    }
    fn(1);



版权声明:本文为ding139725原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。