flv.js源码知识点(下)FLV格式解析

在flv.js系列的最后一章中,我们将仔细研究解析FLV格式。
FLVDemuxer是flv.js的核心组件,但在了解它之前,您必须首先熟悉FLV文件的数据结构以及如何在JavaScript中处理二进制数据。
FLV文件采用Adob​​e的FlashVideo格式,由固定的FLVHeader和可变的FLVBody组成。
FLVHeader包含9个字节的类型、大小等固定信息,而FLVBody则由多个标签组成,每个标签由TagHeader和TagData组成。
理解这些结构对于解析非常重要。
要操作FLV数据,您需要熟悉JavaScript的ArrayBuffer和DataView用法。
DataView类提供了用于读取各种字节类型的API,例如getUint8和getUint32。
了解字节顺序(小端和大端)也很重要。
此外,在处理多字节数据和特定位信息时,位操作技术(例如按位AND、OR、XOR和位移位)非常有用。
总的来说,了解FLV格式的详细结构以及熟练使用二进制数据读取技术是解析flv.js源码的关键。
下一步是根据FLV规范逐字段解析据。

深入JavaScript运行原理

浏览器如何工作您是否想知道JavaScript代码是如何在浏览器中执行的?

在此执行过程中,在HTML解析过程中会遇到JavaScript标签。

它停止解析HTML并加载并执行JavaScript代码;

那么谁来执行JavaScript代码呢?

JavaScript引擎

为什么我们需要JavaScript引擎?高级编程语言必须转换为最终的机器指令才能执行;当然,我们编写的JavaScript传递给浏览器或者任务节点,最终都要由CPU来执行。
然而,CPU只知道我们自己的一组机器语言指令,这些指令可以被CPU执行,将JavaScript代码翻译成CPU指令;

Google将开源Chrome和Node.js等中使用的高性能JavaScript和Web汇编引擎。

它现了ECMAScript和WebAssembly,并在带有宏10.12+的Windows7或更高版本以及使用x64、IA-32、ARM或MIPS处理器的Linux系统上运行。

V8可以独立运行,也可以嵌入到任何C++应用程序中

go)

>

该对象的所有作用域均可访问;

包含Date和Arr。
ay、String、Number、setTimeout、setInterval等;

还有一个window属性引用自身;

运行代码

面写着。
js引擎中的执行上下文栈(ExecutionContextStack,简称ECS)是用来执行代码的调用行栈,我们可以通过JavaScript:

parse模块将JavaScript代码转换为AST(抽象语法树),因为。
口译员则不然。
直接理解JavaScript代码;

如果函数没有被调用,则不会转换为AST;

ParseV8官方文档:https://v8.dev/blog/scanner

Ignite将AST转换为字节码的解释器。

同时收集TurboFan优化所需的信息(比如函数参数信息,只能对类型进行真正的操作)。

如果函数是仅调用一次,Ignition执行执行注解ByteCode;

LauncherV8官方文档:https://v8.dev/博客/启动翻译器

TurbofanCPU可以将字节码编译成可以直接执行的机器代码;

如果一个函数被多次调用,那么它就会被标记。
作为热点任务,然后通过TurboFan转换为优化的机器代码,以提高代码的性能。

但是,如果函数的类型在后续执行时发生变化(例如sum函数最初实现了数字类型,后来变成了字符串),则机器代码实际上会恢复为字节码。
type),之前优化的机器码无法正确处理该作业,因此将其反向转换为字节码(官方)V8实现细节

Parser直接将符号转换为AST树转换结构。
;

准备器准备为什么有必要吗?

这是因为并非所有JavaScript代码都会首先执行。
那么解析所有的JavaScript代码会影响网站的性能;

因此V8引擎实现了惰性解析方案,用于预先解析不必要的函数。
暂时只需要解析内容即可,调用函数时并没有解析整个函数。
我们的JavaScript源代码解析了吗?

将源代码烧录到V8引擎,它得到一个流。

对源代码进行转换和编码;

扫描器执行解析,解析将代码转换为令牌。
经过Parser和Preparser之后:

AST树创建后,通过inflaming转换为字节码。

Javascript执行流程1.初始化全局对象

js引擎代码执行之前,会在堆内存中创建一个全局对象:GlobalObject(GO)

这个对象的所有功能都可以访问范围;

包括日期、数组、字符串、er、setTimeout、setInterval等;

也指自身。
有窗口功能;

2.执行上下文堆栈(CallStack)

在js引擎中是执行上下文堆栈(ExecutionContextStack,简称ECS),它是用来执行代码的调用堆栈。

那么现在谁来执行呢?执行的全局代码块:

全局代码块构造一个全局执行上下文(GEC)来执行;

GEC转储到ECS中执行;

GEC放入ECS中,它由两部分组成:

>

这个过程也叫提升变量的作用域

第一部分:代码执行前,解析器转换为AST的过程,全局定义的变量、函数等被添加到GlobalObject中。
它们不会被赋值;

第2部分:在代码执行或执行操作期间为变量赋值。
其作用;

3.GEC进入ECS4.GEC代码执行开始范围提升

第二个发布号1出现未定义

全局代码执行过程函数

这里打印了name,但是在函数foo中找不到name。
,根据动态正确搜索路径的链中搜索的规则,在父作用域中找到该名称,这里父作用域是全局的,因此在转换解析器的过程中打印了它。
AST、全局定义的变量、函数等被添加到GlobalObject,但不分配值。
bar函数在这里放置内存地址0xb00,表示对应的内存位置。
Number:123等

执行第13行代码时,调用bar函数,然后在函数的调用堆栈中创建函数执行上下文

查找是否不存在转到顶部作用域->查找作用域链中的顶层并查找name='why',因此最后打印的是'why'。

函数调用函数执行流程

打印输出:HelloGlobal

执行流程:begin,preset{message:undefined,foo:0xa00,bar:0xb00};然后执行代码为每一项赋值{message:"heologylobal",foo:0xa00,bar:0xb00};按照顺序,先执行bar(),再调用bar(),然后里面有一个函数执行上下文是AO,消息是从var存到AO中的,然后调用foo(),还有一个函数执行上下文,这里实现的代码是打印一条消息,所以要搜索第一件事是,如果foo()中是否有消息,它会在父级中查找消息链,因此它会打印为“helloglobal”。
我们所解释的所有内容都是基于以前的ECMA版本规范:

在最近的ECMA版本规范中,修改了一些术语:

通过以上的改变,我们可以看到,根据新的ECMA标准,我们之前的变量对象VO已经有了另一个名字,叫做变量环境VE。

科学推广面试题

第一题

varn=100;functionfoo(){n=200}foo()console.log(n)

输出结果:200

{n:undefined,foo:0xa00},然后给n赋值,当这里调用函数foo时,函数执行上下文创建完毕,执行代码n=200,那么如果在foo函数对象中没有找到n,则去顶层在parent中查找n并赋值200,所以相当于设置了过程中的价值,因此最终打印时的价值。
n为200。

n)

第二个查询

functionfoo(){console.log(n)varn=200console.log(n)}varn=100foo()

结果:未指定;200

分析:

问题3

varn=100functionfoo1(){console(n)//2,100}functionfoo2(){varn=200console.log(n)/1,200foo1()}foo2()console.log(n)//3,100

结果:见注释

查询4

vara=100functionfoo(){console.log(a)returnvara=100}foo()

结果输出:未定义

分析:

>

问题5

functionfoo(){vara=b=100//相比vara=10//b=10//这里没有定义b,js默认将其设置为全局}foo()console.log(a)console.log()b)

输出输出:未定义;10

原文:https://juejin.cn/post/7099834026541711391

图文剖析h3.js四则运算源码

h3.js是一个小型而高效的JavaScript库,专门设计用于处理任意精度的十进制算术。
在常规项目中,算术运算可能会导致精度损失,影响结果的准确性。
h3.js就是为了解决这个问题而设计的。
与h3.js类似的库包括h3number.js和decimal.js,它们也是由MikeMcl创建的。
作者在这里详细阐述了这三个库的区别。
h3.js是最小、最简单的任意精度计算库,方法数量最少,大小也最小。
h3number.js和decimal.js以更高的基数存储值,因此在处理大数字时速度更快。
对于金融应用,h3number.js可能更合适,因为除非涉及除法运算,否则它可以保证准确性。
本文将通过分析h3.js的解析函数和加减乘除运算的源码来了解作者的设计思路。
在四种算术运算中,除法运算是最复杂的。
创建Big对象时,new运算符是可选的。
构造函数中的关键代码如下。
您可以使用不带new关键字的构造函数。
如果传入参数已经是Big的实例对象,则复制其属性,否则使用parse函数创建属性。
parse函数向实例对象添加三个属性。
这种表示方式类似于IEEE754双精度浮点数的存储方式。
JavaScript的Number类型由64位二进制格式IEEE754值表示,其中64位用于表示3个部分。
下面以Big('123400')、Big('0.1234')、Big('100e2')为例分析parse函数转换的详细过程。
注意:只有当Big('100e2')中的100e2作为字符串传入时才能检测到e。
在执行解析之前,数字形式的Big(100e2)将转换为Big(10000)。
最后,Big('123400'),Big('-0.1234'),Big('100e2')会被转换为...至此,parse函数逻辑结束。
接下来我们分别分析加、减、乘、除运算。
在加法运算的源码中,k用于保存进位值。
上面的过程可以用一个图来表示……减法运算的源码和加法类似,这里不再赘述。
减法的核心逻辑如下...减法的过程可以用一个图来表示,其中xc代表被减数,yc代表减数...乘法运算的源码中,主要逻辑如下...描述的是我们之前在纸上写的进行乘法运算的过程。
以123*12为例...除法运算中,对于a/b来说,a是被除数,b是除数...注意:h3.js使用数组来存储值,类似于高精度计算,但它是在数组中的每个位置存储一个值,然后对每个位置进行操作。
对于超大数,h3.js的算术运算可能没有h3number.js那么快...使用h3.js进行运算时,有时没有设置足够大的精度会导致结果不准确...总结:这个文章分析了h3.js的解析函数和四种算术运算源码,用图文并茂的方式详细描述了运算过程,逐渐还原了作者的设计思路。
如有不准确或不同意见,欢迎提出。