个人对javascript预编译的理解

乄清雅轩灬 乄清雅轩灬     2022-08-29     458

关键词:

什么是js的预编译

马上要找工作了,之前学习JS都是很基础的皮毛,作为当前最火热的语言,本人一定是要研究的,然而刚接触到预编译我就快疯了,对于一个脑子不好使的人来说真的太绕了,饶了好久也不知道有没有绕明白,所以先记载下来,以后发现有啥不对的再纠正。

首先,JS解释器在执行一段script脚本时,首先会进行预编译,将代码中声明的变量和函数进行处理,然后才会按代码顺序翻译执行,那么JS在预编译和执行阶段分别进行了些什么操作呢?网上有很多大神的帖子给了说明:

1. 在执行代码前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义

2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找;遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)

看完之后我的表情是懵逼的,内心是崩溃的,,,活动对象啊,prototype啊都是什么鬼,(原谅本人是一个小白,这些东西都不懂),最后经过自己尝试,总结了一下

1.预编译阶段,首先会将所有以var显示声明的变量,或者"变量式"函数提到最前面创建,不管他们在声明时同时进行赋值与否,预编译创建时都给他们赋值undefined;对于"定义式"函数声明,即用function声明的函数,其函数也会被提出来创建,但是创建后赋值的内容是该函数定义本身;另外,var显示声明的变量会先于定义式函数被创建

2.上述预编译结束后,js代码按照代码顺序解释执行,当遇到赋值语句时,再更改之前预编译过的变量的值,如var a = 11;在预编译阶段,a变量会被提出来创建,赋值undefined,在执行阶段,当执行到这条语句,将11赋给a

FOR INSTANCE

呐,基本就是这样,下面用几个例子详细说明一下,答案会在后边给出,可以自己先想一下结果是什么~

<script type="text/javascript">
console.log(a);
var a = 1;
console.log(fa);
fa();
function fa(){
    console.log("方法fa()");
}
console.log(fb);
fb();
var fb = function(){
    console.log("方法fb()");
}
fb();
</script>

像Java如果在一个变量被创建前使用这个变量,一定会报错,但是js在执行前经过了预编译事先创建了变量,所以不会报错;

首先进行预编译阶段,先将所有的变量和函数提到前面创建,并赋相应的初始值,上述的代码进过预编译处理等价成下面的代码形式:

<script type="text/javascript">
var a = undefined;
var fb = undefined;
function fa(){
    console.log("方法fa()");
}
console.log(a);
a = 1;
console.log(fa);
fa();
console.log(fb);
fb();
fb = function(){
    console.log("方法fb()");
}
fb();
</script>

首先,被var声明的变量首先被前置,创建,赋值,其次是定义式函数的预编译处理;当预编译结束,进入执行阶段,从上往下顺序执行:

1)遇到了第一个console.log(a),由于事先经过了预编译创建了a变量,所以输出undefined;

2)再向下顺序执行,遇到了a=1赋值语句,此时将1赋值给了a;

3)继续,console.log(fa),fa是定义式函数,预编译赋值内容为函数的定义,输出

function fa(){

  console.log("方法fa()");

}

4)执行fa(),即调用了fa函数,输出 方法fa()

5)执行console.log(fb),输出undefined

6)执行fb(),报错!Uncaught TypeError: fb is not a function,因为fb当前仍然是变量,还没有执行将函数赋给fb的操作;

7)将上行代码注释,继续执行,此时才将一个函数赋值给了fb

8)再次执行fb(),输出 方法fb()

另一个例子

<script type="text/javascript">
console.log(aNumber);
var aNumber = 100;
tweak();
function tweak()  {
    var newThing = 0;
    console.log(newThing);
    newThing = aNumber;
    aNumber = 42;
    if (false)  {
        var aNumber; 
        aNumber = 123; 
    }
    console.log(aNumber);
    console.log(newThing);
}
console.log(aNumber);
</script>

首先还是要预编译,注意,此处有两个aNumber,一个是全局的,一个是在if代码段中的局部变量,全局变量的aNumber被预编译处理是毋容置疑的,然而,即使if语句不会被执行,但是预编译发现了if代码段中声明的aNumber局部变量,也会进行预编译!也就是说,预编译君照吃不误,不管你是全局变量、局部变量、执行时这个变量用得着还是用不着,只要显示的用var声明了,都会进行预编译,不过此处的两个aNumber作用域是不同的;

其次是tweak()定义式函数也会被预编译,预编译结束,进入执行阶段,下面公布作业答案~

undefined  0  42  undefined  100

可以在试一下,将代码var aNumber = 100;注释掉又会发生什么?

在执行第一句console.log(aNumber)就会报错!这是为啥?

因为全局变量被注释掉了,现在只有if代码块的aNumber被预处理创建,在作用域外调用局部变量当然不行了

总结

1)首先,JS执行脚本前会将所有的变量、函数预编译,且变量先于函数预编译

<script type="text/javascript">
console.log(fc);//输出fc方法的定义部分,如果变量和函数同名,则先预编译变量,后预编译函数,函数的声明就覆盖了变量
function fc(){
    console.log("fc方法");
}
var fc = "fc变量";
console.log(fc);//执行阶段,对fc赋值为"fc变量"
</script>

可以看到,即使fc变量的定义语句在fc函数定义语句之后,但是预编译时还是会先预编译fc变量,同名情况下,后预编译的覆盖了前面的内容

2)注意,JS中变量可以隐式创建,但是这类变量应该不会被预编译,类似下面的形式会报错;

<script type="text/javascript">
console.log(c);//Uncaught ReferenceError: c is not defined
c =5;
</script>

还有就是,在局部代码块中隐式创建的变量当做全局变量使用

3)最后,JS是按<script>代码块分块执行的,且上一个script块中的变量在下一个script中仍然适用;反之则不行,如

<script type="text/javascript">
var a = 2;
console.log(c);//Uncaught ReferenceError: c is not defined
</script>

<script type="text/javascript">
var c = 5;
console.log(a);//2
</script>

个人理解的感觉还是有些出入,有什么错误还望各位dalao指正

javascript——作用域和预解析,深度理解代码执行程序(代码片段)

博主是👦一个帅气的boy,你可以叫我山鱼君🖱⌨个人主页:山鱼君🐟的个人主页💖💖如果这篇文章对你有帮助的话希望三连下👍⭐✍支持一下博主🌊如果有什么建议的话可以在评论区留言... 查看详情

浅谈javascript预编译原理

这两天又把js的基础重新复习了一下,很多不懂得还是得回归基础,大家都知道js是解释性语言,就是编译一行执行一行,但是在执行的之前,系统会做一些工作:1,语法分析;2,预编译;3,解释执行。语法分析很简单,就是引擎... 查看详情

对编译器是什么,以及对编译过程的一点个人理解

(写的像玄学一样,但我自己还是有点道理的。)   查看详情

javascript预编译流程详解(代码片段)

1-JavaScript运行三部曲1.语法分析2.预编译3.解释执行语法分析很简单,就是引擎检查你的代码有没有什么低级的语法错误;解释执行顾名思义便是执行代码了;预编译简单理解就是在内存中开辟一些空间,存放一些变量与函数;2-J... 查看详情

对javascript的原型,原型链和继承的个人理解

继承是OO语言中一个最为人津津乐道的概念,也是初接触Javascript的初学者难理解的概念=。=继承主要分为两种:一种是接口继承,另一种是实现继承。而在ECMAScript中只支持实现继承,所以我们今天来讨论讨论实现继承。实现继承... 查看详情

9月九日作业:对编译原理的个人理解

1.编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。2.学习编译原理可... 查看详情

谈个人对avascript面向对象的理解

javascript,不但是javascript或者是别的语音,大多数都有一句经典的话:一切皆对象。下面谈谈我个人对面向对象的理解,为什么要用面向对象来写js,这话我思考了很久,最后得出的结论就是:1、调用函数方便,很方便。2、最重... 查看详情

javascript预编译

...详细讲解一下大家要明白,这个预编译和编译是不一样的JavaScript是解释型语言,既然是解释型语言,就是编译一行,执行一行传统的编译会经历很多步骤,分词、解析、代码生成什么的日后有时间再给大家科普下 查看详情

预编译作用域链和闭包理解

在理解预编译之前,首先了解一下JS的解析过程:JS引擎在解析脚本的过程分为两个阶段,预编译和执行,首先预编译然后再从上之下一行一行的执行代码。其次,要了解作用域,作用域是一个变量或者函数能够使用的空间,分... 查看详情

js预编译

...明整体提升2.变量声明提升其实还有一点最重要的就是预编译,预编译往往发生在函数执行前,了解预编译,对我们理解函数执行非常关键。预编译的前奏1.implyglobal暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量... 查看详情

javascript的预编译过程

你真的了解javascript的预编译过程吗?目录你真的了解javascript的预编译过程吗?预编译发生在哪一步呢?js三步曲语法解析预编译解释执行预编译发生在哪一步呢?首先要知道js的预编译发生在哪一步也就是你跟你... 查看详情

理解问题:预编译的标头和包含用法

】理解问题:预编译的标头和包含用法【英文标题】:Comprehensionissue:Precompiledheaders&includeusage【发布时间】:2015-08-0915:16:07【问题描述】:我遇到了关于预编译头文件和#include指令使用的理解问题。所以我在这里得到了我的“s... 查看详情

js执行顺序预编译

...sole.log(a);//1预解析函数f();//1functionf(){console.log(1);};详细:javascript变量声明提升(hoisting)分块执行代码js是按块执行代码的,所谓代码块就是使用<script> 查看详情

Javascript - 预编译的正则表达式性能

】Javascript-预编译的正则表达式性能【英文标题】:Javascript-Precompiledregexperformance【发布时间】:2013-02-1823:38:12【问题描述】:在this帖子中,据说预编译正则表达式将提高脚本性能。作者通过performancetest证明了这一点。但是,据... 查看详情

javascript预编译(代码片段)

预编译分为两种:函数预编译(函数执行的前一刻执行)全局预编译(页面加载完成时执行)函数执行编译步骤:创建ActivationObject找形参和变量声明,将变量声明和形参作为AO的属性名,值为undefined将实参和形参值统一在函数体内找函... 查看详情

javascript预编译(代码片段)

预编译分为两种:函数预编译(函数执行的前一刻执行)全局预编译(页面加载完成时执行)函数执行编译步骤:创建ActivationObject找形参和变量声明,将变量声明和形参作为AO的属性名,值为undefined将实参和形参值统一在函数体内找函... 查看详情

javascript的预编译和执行

 JavaScript引擎,不是逐条解释执行javascript代码,而是按照代码块一段段解释执行。所谓代码块就是使用<script>标签分隔的代码段。整个代码块共有两个阶段,预编译阶段和执行阶段一、编译阶段对于常见编译型语言(例... 查看详情

你不知道的javascript1(作用域与闭包)(代码片段)

1.编译原理:首先,JavaScript是解释性语言,编译一行,执行一行JavaScript运行三部曲:1.语法分析2.预编译3.解释执行语法分析:js引擎来检查代码是否存在语法错误预编译:简单理解,就是在内存中开辟一些空间来声明存放一些变... 查看详情