JavaScript高级程序设计笔记04 变量、作用域与内存
变量、作用域与内存
变量
特定时间点一个特定值的名称。
分类
原始值:按值访问
- 复制:两个独立使用、互不干扰
引用值(由多个值构成的对象):按引用访问
操作对象时,实际上操作的是对该对象的引用(reference)而非实际的对象本身
- 复制:复制的值实际上是一个指针,指向存储在堆内存中的对象。实际上两个变量指向同一个对象
- 函数传参:都是按值传递,如果是引用值,就跟引用值变量的复制一样
判断类型
typeof
最适合用来判断一个变量是否为原始类型,对引用值的用处不大。
instanceof
什么类型的对象(由对象的原型链决定)
作用域
执行上下文
变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。每个上下文都有一个关联的变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。
全局上下文是最外层的上下文。根据ECMAScript实现的宿主环境,表示全局上下文的对象可能不一样。在浏览器中,就是常说的window对象。
上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数。
上下文栈。当代码执行流进入函数时,函数的上下文被推倒一个上下文栈上;在函数执行完毕之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。
作用域链(scope chain)。决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域链的最前端;全局上下文的变量对象始终是作用域链的最后一个变量对象。上下文之间的连接是线性的、有序的,内部可以访问外部,外部无法访问内部。
函数参数被认为是当前上下文中的变量。
标识符解析。搜索过程始终从作用域链的最前端开始,逐级往后,直到找到或者到达最后端。
局部作用域中定义的变量会产生遮蔽(上层同名变量)效果,引用全局变量可以使用完全限定的写法:window.propName。
增强作用域链
在作用域链前端临时添加一个上下文。
- try/catch的catch语句:创建一个新的变量对象(包含要抛出的错误对象的声明)
- with:添加指定的对象
eval():修改作用域链。
不同关键字的声明
var
通过var定义的全局变量和函数都会成为window对象的属性和方法。
使用var声明变量时,变量会被自动添加到最接近的上下文。
会导致变量声明被提升,在(代码中)变量声明之前就可以访问到变量。
let/const
顶级声明不会定义在全局上下文中,但在作用域链解析上效果是一样的。
块作用域由最近的一对包含花括号界定。不能重复声明。
const声明不能重新赋值,单一类型且不可修改。
V8引擎针对const的优化:const声明的变量都替换成实际的值,而不通过查询表进行变量查找。
变量查找(作用域链)
标识符查找:局部上下文->沿作用域链
访问局部变量比全局变量要快,因为不用切换作用域。
垃圾回收。GC
执行环境负责在代码执行时管理内存(内存分配和闲置资源回收)。
基本思路:确定哪个变量不会再使用,然后释放它占用的内存。此过程是周期性的,每隔一定时间就会自动运行。(近似且不完美的方案,是否还有用属于“不可判定”的问题。不是所有时候都会很明显)
如何标记未使用的变量,两种主要的标记策略:
标记清理mark-and-sweep:最常用
过程:
- 标记内存中存储的所有变量;
- 将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉;
- 之后再被加上标记的变量,就是待删除的了,因为任何在上下文中的变量都访问不到它们了;
- GC程序做一次内存清理,销毁带标记的所有值并收回它们的内存。
引用计数reference counting
GC下次运行的时候会释放引用数为0的值的内存。
严重的问题:循环引用。典型:IE8及更早版本的BOM和DOM(使用COM对象)。
应该在确保不使用的情况下切断原生JavaScript对象与DOM元素之间的连接。
把变量设置为null实际上会切断变量与其之前引用值之间的关系。
GC调度(性能)
最好的办法:写代码时做到,无论什么时候开始收集垃圾,都能让它尽快结束工作
现代GC程序会基于对JavaScript运行时环境的探测来决定何时运行。
探测机制:基本上是根据已分配对象的大小和数量来判断。(V8的堆增长策略:根据活跃对象的数量外加一些余量来确定何时再次垃圾回收。)
不推荐主动触发垃圾回收。(某些浏览器可以)
- 减少GC次数(减少不合理分配)
- 尽快完成回收
内存管理
分配给浏览器的内存通常比分配给桌面软件的要少很多,分配给移动浏览器的更少。——> 主要出于安全考虑,避免运行大量JavaScript的网页耗尽系统内存而导致操作系统崩溃。
这个内存限制不仅影响变量分配,也影响调用栈以及能够同时在一个线程中执行的语句数量。
内存占用量保持在一个较小的值可以让页面性能更好。优化内存占用的最佳手段:保证在执行代码时只保存必要的数据。如果数据不再必要就解除引用(设置为null)——尤其是全局变量和全局对象的属性,下次垃圾回收时会被回收。
利用let/const提早回收:块作用域比函数作用域更早终止
v8引擎的隐藏类:几个实例共享同一个构造函数和原型。
给实例增加新属性或删除其属性,就不能共享一个隐藏类。——最佳实践:不想要的属性设置为null,达到删除引用值供GC程序回收的效果。
避免“先创建再补充”式的动态属性赋值。
内存泄漏
- 意外声明全局变量
- 闭包
静态分配与对象池(合理分配,避免多余GC:保住因释放内存而损失的性能)
减少浏览器执行垃圾回收的次数。
浏览器决定何时运行GC程序的一个标准,就是对象更替的速度。——》一个策略:使用对象池(管理一组可回收的对象)
可使用数组来维护,但必须留意不要招致额外的垃圾回收。
JavaScript高级程序设计笔记04 变量、作用域与内存的更多相关文章
- 《JavaScript高级程序设计》Chapter04 变量,作用域,内存
原始值&引用值 原始值(primitive value):Undefined, Null, Boolean, Number, String, Symbol 按值访问,直接操作存储在变量中的实际 ...
- Javascript高级程序设计——执行环境与作用域
Javascript中执行环境是定义了变量或函数有权访问的其他数据,决定了各自的行为,每个执行的环境都有一个与之关联的变量对象,环境中定义的所以变量和函数都保存在这个对象中. 全局执行环境是最外围的一 ...
- javascript高级程序设计--笔记01
概述 JavaScript的实现包含三个部分: 1 核心(ECMAScript) 提供核心语言功能 2 文档对象模型(DOM) 一套提供了访问以及操作网页内容的API 3 浏览器对象模型( ...
- JavaScript高级程序设计笔记(一)
---恢复内容开始--- 前三章为基础知识,为了方便以后查看,所以比较啰嗦.这里对函数的基本操作没有记录. 1.JavaScript的实现 虽然 JavaScript 和 ECMAScript 通常都 ...
- JavaScript高级程序设计笔记之面向对象
说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...
- Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)
var obj = {'a':'a'}; var fun = function (){} console.log(typeof obj);//object console.log(typeof fun ...
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...
- javascript高级编程笔记04(基本概念)
Function类型 Es5中规范了另一个函数对象的属性:caller,这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,这它的值为null function outer() ...
- javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记
1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...
- javaScript高级程序设计笔记 2
Undefinde Null Boolean Number String 基本类型 Object 引用类型 只有引用类型才能动态的添加属性 赋值基本类型和引用类型也不相同,复制的基本类型的 ...
随机推荐
- 文心一言 VS 讯飞星火 VS chatgpt (67)-- 算法导论6.5 6题
文心一言 VS 讯飞星火 VS chatgpt (67)-- 算法导论6.5 6题 六.在 HEAP-INCREASE-KEY 的第 5 行的交换操作中,一般需要通过三次赋值来完成.想一想如何利用IN ...
- windows相关DOS命令简介与基操
作为程序员要求掌握最基本的windows相关的DOS命令(详细版) 一.DOS命令.cmd.windows操作系统中保留的DOS命令分别是什么? 1.DOS命令是什么? DOS命令,计算机术语,是指D ...
- form 表单恢复初始数据
1 表单数据的保存和恢复方法 1.1 前端数据保存方法 在前端,我们可以使用两种方法来保存表单数据:LocalStorage 和 Cookie. 使用 LocalStorage 保存数据:LocalS ...
- Health Kit基于数据提供专业方案,改善用户睡眠质量
什么是CBT-I? 中国社科院等机构今年发布的<中国睡眠研究报告2023>内容显示,2022年,受访者的每晚平均睡眠时长为7.40小时,近半数受访者的每晚平均睡眠时长不足8小时(47.55 ...
- QTreeView自绘实现酷炫样式
本篇文章结合笔者的经历,介绍一种通过重写QTreeView绘制事件,使用QPainter来实现好看的列表的方式. 导语 Hi,各位读者朋友,大家好.相信大家在日常的工作中,经常会接触到QTreeVie ...
- VS2015项目.net-framework-4.5.2升级或新建项目无法选择framework 4.6.2(解决办法)
VS2015里面没有.NET Framework 4.6.2 VS2015默认安装的目标框架最高是.NET Framework 4.6.1,但是我的项目里面某些NuGet软件包更新需要依赖.NET F ...
- 11、Spring之基于注解的AOP
11.1.环境搭建 创建名为spring_aop_annotation的新module,过程参考9.1节 11.1.1.配置打包方式和依赖 注意:AOP需要在IOC的基础上实现,因此需要导入IOC的依 ...
- AI绘画| 迪士尼风格|可爱头像【附Midjourney提示词】
Midjourney案例分享 图片预览 迪士尼风格|可爱头像 高清原图及关键词Prompt已经放在文末网盘,需要的自取 在数字艺术的新时代,人工智能绘画已经迅速崭露头角.作为最先进的技术之一,AI绘画 ...
- AI绘画创意文字全流程揭秘,你的终极文字艺术实操宝典
本教程收集于:AIGC从入门到精通教程汇总 AIGC技术不断更新迭代,国内出现了越来越多的新玩法,比如最近大家都在热议的AI绘画创意文字. 过去的一周,我把这些新玩法都研究了一遍,并总结了一套完整的制 ...
- 《Linux基础》03. 运行级别 · 实用指令
@ 目录 1:运行级别 2:帮助指令 2.1:man 2.2:help 3:文件目录指令 3.1:pwd 3.2:ls 3.3:cd 3.4:mkdir 3.5:rmdir 3.6:touch 3.7 ...