当前位置: 首页 > Web前端 > JavaScript

JavaScript高级编程笔记04变量、作用域和内存

时间:2023-03-27 01:49:46 JavaScript

特定时间点的变量名和特定值。分类原始值:按值访问复制:两个独立使用的、互不干扰的引用值(由多个值组成的对象):按引用访问对象时,实际上是对对象的引用进行操作,而不是非实际复制对象本身:复制的值实际上是指向存储在堆内存中的对象的指针。实际上,两个变量指向同一个对象函数参数:两者都是按值传递的。如果是引用值,则与引用值变量的副本相同。typeof最适合判断一个变量是否是原始类型。没什么用。instanceof什么类型的对象(由对象的原型链决定)scopeexecutioncontext变量或函数的上下文决定了它们可以访问哪些数据以及它们的行为方式。每个上下文都有一个关联的变量对象(variableobject),所有在这个上下文中定义的变量和函数都存在于这个对象上。全局上下文是最外层的上下文。根据ECMAScript实现的宿主环境,表示全局上下文的对象可能不同。在浏览器中,它通常被称为窗口对象。上下文在其所有代码执行后被销毁,包括在其上定义的所有变量和函数。上下文堆栈。当代码执行流进入一个函数时,函数的上下文被压入上下文栈;函数执行后,上下文栈会弹出函数上下文,将控制权返回到之前的执行上下文。作用域链。确定每个上下文级别中的代码访问变量和函数的顺序。代码执行上下文的变量对象总是在作用域链的前端;全局上下文的变量对象总是作用域链的最后一个变量对象。上下文之间的连接是线性有序的,内部可以访问外部,外部不能访问内部。函数参数在当前上下文中被视为变量。标识符解析。搜索过程总是从作用域链的前端开始,向后进行,直到找到或到达末端。定义在局部范围内的变量会产生阴影效果(上层同名变量)。要引用全局变量,可以使用完全限定的写法:window.propName。增强作用域链临时在作用域链的前端添加上下文。try/catch的catch语句:创建一个新的变量对象(包含要抛出的错误对象的声明)with:添加指定的对象eval():修改作用域链。不同关键字var的声明var定义的全局变量和函数将成为window对象的属性和方法。使用var声明变量时,变量会自动添加到最近的上下文中。会导致变量声明被提升,在变量声明之前(在代码中)就可以访问变量。let/const顶级声明未在全局上下文中定义,但对作用域链解析具有相同的效果。块作用域由最近的一对封闭花括号分隔。声明不能重复。const声明不能重新分配,具有单一类型且不能修改。V8引擎对const的优化:将const声明的变量替换为实际值,而不是通过查找表查找变量。变量查找(作用域链)标识符查找:局部上下文->沿作用域链访问局部变量比全局变量更快,因为不需要切换作用域。垃圾收集。GC执行环境负责代码执行期间的内存管理(内存分配和闲置资源回收)。基本思路:判断哪个变量将不再使用,然后释放它占用的内存。此过程是周期性的,并会定期自动运行。(近似和不完美的解决方案,是否仍然有用是一个“不确定”的问题。并不总是很明显)如何标记未使用的变量,两种主要标记策略:mark-and-sweep:最常用的Process:标记所有存储的变量在记忆中;移除上下文中的所有变量以及上下文中变量引用的变量;后面标记的变量要被删除,因为上下文中的任何变量都没有上下文中的变量可以访问它们;GC程序做一次内存清理,销毁所有标记的值并回收它们的内存。引用计数referencecountingGC下次运行时会释放值为0的内存。严重问题:循环引用。典型:IE8及更早版本的BOM和DOM(使用COM对象)。原生JavaScript对象和DOM元素之间的连接在保证不被使用时应该被切断。将变量设置为null有效地切断了变量与其先前引用的值之间的关系。最好的GC调度方式(性能):写代码的时候,不管垃圾回收什么时候开始,都能尽快结束它的工作。现代GC程序将根据对JavaScript运行时环境的检测来决定何时运行。检测机制:基本上基于分配对象的大小和数量。(V8的堆增长策略:根据活动对象的数量加上一些余量来决定何时再次进行垃圾回收。)不建议主动触发垃圾回收。(部分浏览器可以)ReducethenumberofGCs(减少不合理分配)尽快完成回收内存管理分配给浏览器的内存通常比分配给桌面软件少很多,移动端浏览器更少。——>主要是出于安全考虑,避免运行大量JavaScript网页耗尽系统内存,导致操作系统崩溃。这个内存限制不仅会影响变量分配,还会影响调用堆栈和一个线程中可以同时执行的语句数。保持较小的内存占用量可以提高页面性能。优化内存使用的最佳方法是确保在执行代码时只保存必要的数据。如果不再需要数据,则取消引用(设置为null)——尤其是全局变量和全局对象的属性,它们将在下一次垃圾回收中回收。使用let/const的早期回收:块作用域比函数作用域更早终止V8引擎的隐藏类:多个实例共享相同的构造函数和原型。您不能通过向实例添加新属性或从实例中删除属性来共享隐藏类。——最佳实践:将不需要的属性设置为null,达到删除引用值的效果,供GC程序回收。避免“先创建后补充”的动态属性赋值。内存泄漏全局变量的意外声明Closure静态分配和对象池(合理分配,避免冗余GC:保持因释放内存而造成的性能损失)减少浏览器执行垃圾回收的次数。浏览器决定何时运行GC程序的标准之一是对象替换的速度。——》一种策略:使用对象池(管理一组可回收对象)可以使用数组来维护,但必须注意不要招致额外的垃圾回收。