js预编译原理

news/2024/10/18 18:27:20/

预编译(Hoisting)是指在代码执行之前,JavaScript 引擎会将变量和函数的声明提升到当前作用域的顶部

这意味着在代码中,变量和函数的声明可能在实际代码执行之前 已经被处理了。(提升优先级:函数>变量)

变量提升规则

这里要提前讲清楚变量提升的规则

x=5 
var x
console.log(x)//输出5console.log(global)
global=100
var global 
//输出undefined

使用 var 声明的变量会存在声明提升 ,但是声明具体的值之前访问变量,但其值为 undefined

  console.log(v1);var v1 = 100;function foo() {console.log(v1);var v1 = 200;console.log(v1);}foo();console.log(v1);

概况

  • 在进入执行环境(函数)时,就会创建一个新的变量环境,用来存储该执行环境中的所有变量和函数。
  • 变量环境中的变量和函数会进行预处理(变量提升)并赋予初始值(undefined)。
  • 在代码执行阶段,变量会被赋予实际值。

预编译全局三部曲

1. 创建GO对象(Global Object)

当编译器开始编译整个js代码时,首先会创建一个执行上下文对象GO对象(Global Object)

2. 变量声明

将变量声明作为GO对象的一个属性名,其值初始化为undefined

3. 在全局找函数声明

将函数名作为Go对象的属性名,其值初始化为该函数体

举个例子
global=100
function fn(){console.log(global)global=200console.log(global)var global=300
}
fn()
var global1:创建go对象-->go{ }
2.寻找变量声明不看fn()方法内部,目前之前有 var global 这一个声明go{global:undefined}
3.寻找函数声明
存在 function fn(){ ....}函数声明go{global:undefinedfn: fn函数体}
最后
go{global:100fn: fn函数体}

全局预编译完成,引擎开始执行代码:将100赋值给global,执行函数fn,引擎便开始让编译器编译该函数内部代码

执行函数内部的编译

1.创建AO对象(action object)

编译器编译一个函数时都会为函数创建一个AO(action object)上下文执行对象

2.找形参和变量声明

将变量声明和形参的作为AO的属性名,值为undefined

3.将形参和和实参的值统一

将传入实参的值赋给形参

4.找函数声明

在函数体内寻找函数声明,将函数名作为AO对象的属性名,值赋予函数体

继续这个例子
global=100
function fn(){console.log(global)global=200console.log(global)var global=300
}
fn()
var global1:通过fn的代码创建AO对象AO{ }
2:寻找形参和变量声明作为AO的属性值,先初始为undefined
此时存在一个 var globalAO{global:undefined}
3:将传入实参的值赋给形参,没有形参也没有传入的实参
4:寻找内部函数声明

此时完成完整的代码执行过程:

global=100
function fn(){console.log(global)//函数内有变量声明,//但此时没有赋值,打印undefinedglobal=200//global被赋值为200console.log(global)//输出200var global=300//global被赋值为300
}
fn()
var global最终输出:undefined,200

调用栈

这个概念在闭包也会提到

1. 执行代码先入栈GO执行对象 ,再入栈AO执行对象
2. 调用栈指针 控制了执行顺序,function中找不到变量声明会指向GO对象中再去找。

  1. GO对象先入栈,执行后遇到函数,则创造AO对象入栈
  2. 调用栈指针指向AO对象,引擎开始执行AO对象,
  3. 对函数内执行赋值语句,引擎便会开始在AO对象的环境内寻找该变量声明,并按照先词法环境变量环境的顺序寻找。
  4. 如果没有,调用栈指针便会指向GO对象在该对象的环境内寻找。

所以说是引擎在为函数内部变量赋值时寻找不到变量声明为会往外找(来到全局作用域)

global=100
function fn(){//内部没有变量声明console.log(global)global=200console.log(global)
}
fn()
var global //100,200

例题:c=1直接创造全局变量

g=4
function foo(a){console.log(a)//输出1c=0//创建全局变量var ca=3//如果直接对一个变量赋值而没有使用关键字 var、let 或 const 来声明该变量,这个变量就会变成全局变量。b=2//被覆盖为2console.log(b)//输出2function b(){}function d(){}//虽然在后面有一个同名的函数声明 function b(){},但函数声明并不会覆盖变量的赋值操作console.log(b)//输出2console.log(g,"g")}foo(1)

例题:function 函数提升


function fn(a){console.log(b)//这段代码在函数体中的位置比变量 b 的声明更靠前,因此输出 undefined。//如果下面的b改成:function b(){},则会输出 function b(){}console.log(a);//输出function a(){}//使用 function 关键字声明的函数会进行函数提升(function hoisting),这意味着函数声明会被提升到当前作用域的顶部var a=123console.log(a);//输出123function a(){}//函数声明console.log(a);//输出123var b=function(){}console.log(b);//输出function() b{}var d=aconsole.log(d);//输出123}
fn(1)


http://www.ppmy.cn/news/1425347.html

相关文章

实时数据同步之Maxwell和Canal

文章目录 一、概述1、实时同步工具概述1.1 Maxwell 概述1.2 Canal概述 2、数据同步工作原理2.1 MySQL 主从复制过程2.2 两种工具工作原理 3、MySQL 的 binlog详解3.1 什么是 binlog3.2 binlog 的开启3.3 binlog 的分类设置 4、Maxwell和Canal对比5、环境安装 二、Maxwell 使用1…

MinIO + Prometheus + Grafana docker部署

文章目录 说明MinIO简介MinIO 容器化部署Prometheus服务地址配置方法一:先部署后修改方法二:部署时修改compose文件(未验证) MinIO Access Key配置Prometheus 容器化部署MinIO 生成抓取配置修改Prometheus配置文件Grafana 容器化部…

react经验12:等待状态更新

应用场景: 等待react组件内的state发生变更后进行后续操作。 已知问题 通常state的变化会引起dom的刷新,更新state一般使用setState,但这是个异步操作。 如果此时需要立即操作dom,得到的目标dom是刷新之前的样子。 应对方法 方法1:使用u…

lua的字符串和Table类型实现

字符串 实现在lstring.c中。 字符串类型TString定义如下: typedef union TString {L_Umaxalign dummy; /* ensures maximum alignment for strings */struct {CommonHeader;lu_byte reserved;unsigned int hash;size_t len;} tsv; } TString;字符串内容紧随其后&a…

手机三要素验证不一致的原因有哪些

在当前数字化时代,手机三要素验证已经成为众多业务场景中的关键环节,它是指通过专门的接口技术手段,核实用户提供的姓名、身份证号码及手机号码这三项关键信息的一致性,以确认用户身份的真实性。然而,在实际操作中&…

webAssembly学习及使用rust

学习理解 webAssembly 概念知识,使用 API 进行 web 前端开发。 概念 是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。它有一种紧凑的二进制格式,使其能够以接近原生性能的速度运行。C/C、 C#、Rust等语言可以编译为 …

ARM学习(26)链接库的依赖查看

笔者今天来聊一下查看链接库的依赖。 通常情况下,运行一个可执行文件的时候,可能会出现找不到依赖库的情况,比如图下这种情况,可以看到是缺少了license.dll或者libtest.so,所以无法运行。怎么知道它到底缺少什么dll呢&…

SpringBoot项目中整合MinIO

在Spring Boot项目中整合MinIO&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 添加MinIO依赖 <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.9</version></dependency>2. 配置…