共计 2895 个字符,预计需要花费 8 分钟才能阅读完成。
ECMAScript 变量能够蕴含两种不同类型的数据:原始值和援用值
原生值和援用值的区别
什么是原始值:
最简略的值 例如:Undefined、Null、Boolean、Number、String、Symbol,BigInt。保留原始值的变量是按值(by value)拜访的,因为咱们操作的就是存储在变量中的理论值
什么是援用值:
由多个值形成的对象 例如:Object。援用值是保留在内存中的对象,保留援用值的变量是按援用(by reference)拜访的,因为 JavaScript 不容许间接拜访内存地位,实际上操作的是对该对象的援用(reference)而非理论的对象自身。
区别:
- 动静属性:
原始值:不能有属性
援用值:能够随时增加、批改和删除其属性和办法 -
复制值:
原始值:复制值变量能够独立应用,互不烦扰。let num=123; let num1=num; console.log(num,num1)//123,123 num=100; console.log(num,num1)//100,123
援用值:复制值,复制的是栈中的指针(堆中对象的地址),指向的是同一个对象
let obj={name:"lly",sex:"Man"} let obj1=obj; console.log(obj,obj1)//{name:"lly",sex:"Man"},{name:"lly",sex:"Man"} obj.age=20 console.log(obj,obj1)//{name:"lly",sex:"Man",age:20},{name:"lly",sex:"Man",age:20}
-
传递参数:
原始值:跟原始值变量的复制一样function add(num) { num += 10; return num; } let count = 20; let result = add(count); console.log(count); // 20,没有变动 console.log(result); // 30
援用值:跟援用值变量的复制一样
function setName(obj) {obj.name = "lly";} let person = new Object(); setName(person); console.log(person.name); // "lly"
-
对于类型的判断的办法:
原始类型值:typeof
援用类型值:instanceof
比拟全面的判断办法:Object.prototype.toString.call(要判断的类型值);执行上下文与作用域
什么是执行上下文:
以后 JavaScript 代码被解析和执行时所在环境的抽象概念
执行上下文的品种
1. 全局执行上下文
3. 函数执行上下文
2. 块级执行上下文
什么是作用域:
一个不让变量外泄裸露的独立区域,简略说就是隔离变量的空间,特质:同名变量在不同作用域下互不抵触。
作用域的品种: - 全局作域域
- 函数作用域
- 块级作用域
变量申明的品种以及特色
- var 函数作用域申明
存在变量晋升,在同一作用域内能够反复申明同一变量 - let 块级作用域申明
也存在变量晋升只是暂时性死区缘故导致变量申明之前不可用、在同一作用域内不能申明两次 -
const 常量申明
申明变量必须同时初始化值,一经申明不能从新赋值(对于初始值是原始值,不可从新赋值,对于初始值是援用值,不能从新赋值其余援用,对援用值得键值没有限度),其余特质和 let 雷同。垃圾回收机制
JavaScript 是应用垃圾回收的语言。执行环境负责在代码执行时治理内存。通过主动内存治理实现内存调配和闲置资源回收。实现思路:确定那个变量不在应用,就开释所占内存。垃圾回收的标记策略次要采纳:标记清理和援用计数。
标记清理的原理
来到作用域的值会被主动标记为可回收,而后在垃圾回收期间被删除,先给以后不应用的值加上标记,再回来回收它们的内存
援用计数的原理(不罕用的)
对每个值进行援用次数记录,当援用次数为 0 时,垃圾回收程序下次运行的时候就会开释援用数为 0 的值的内存。
援用次数的规定:
申明变量并给它赋一个援用值时,这个值的援用数为 1。如果同一个值又被赋给另一个变量,那么援用数加 1。相似地,如果保留对该值援用的变量被其余值给笼罩了,那么援用数减 1
性能
垃圾回收程序会周期性运行,频繁的调度垃圾回收程序会重大影响性能,所以浏览器采纳了许多性能优化的计划:
1. 分代收集:对象被分成两组:“新的”和“旧的”。许多对象呈现,实现它们的工作并很快死去,它们能够很快被清理。那些长期存活的对象会变得“老旧”,而且被查看的频次也会缩小
2. 增量收集:
如果有许多对象,并且咱们试图一次遍历并标记整个对象集,则可能须要一些工夫,并在执行过程中带来显著的提早。所以引擎试图将垃圾收集工作分成几局部来做。而后将这几局部会逐个进行解决。这须要它们之间有额定的标记来追踪变动,然而这样会有许多渺小的提早而不是一个大的提早。
3. 闲时收集:
垃圾收集器只会在 CPU 闲暇时尝试运行,以缩小可能对代码执行的影响。
内存治理
1. 通过 const 和 let 申明晋升性能:
因为 const 和 let 以块为作用域不是函数作用域,更早地让垃圾回
收程序染指,尽早回收应该回收的内存。从而改良垃圾回收的过程。
2. 暗藏类和删除操作:
暗藏类:
JavaScript 引擎为了进步性能引入了暗藏类,运行期间,V8 会将创立的对象与暗藏类关联起来,以跟踪它们的属性特色。
function people() {this.name= 'lly';}
let a1 = new people();
let a2 = new people();
a2.sex="Man"
解决方案就是防止 JavaScript 的“先创立再补充”式的动静属性赋值,并在构造函数中一次性申明所有属性。
function people(sex) {
this.name= 'lly';
this.sex=sex
}
let a1 = new people();
let a2 = new people("Man");
删除操作:
应用 delete 关键字会导致生成雷同的暗藏类片段,最佳实际是把不想要的属性设置为 null。
function people() {
this.name= 'lly';
this.sex="Man"
}
let a1 = new people();
let a2 = new people();
delete a1.sex;// 不举荐
a1.sex=null// 最佳实际
3. 导致内存泄露起因以及解决办法:
- 闭包:手动设置 null,切断援用
- 意外的全局变量:应用严格模式或者后面加上申明关键字
- 定时器:不在须要定时器时革除定时器
- DOM/BOM 对象透露 window.onunload 事件上开释内存
4. 动态调配与对象池:
对象池:
JavaScript 优化的一种策略, 用来治理一组可回收的对象。应用程序能够向这个对象池申请一个对象、设置其属性、应用它,而后在操作实现后再把它还给对象池。因为没产生对象初始化,垃圾回收探测就不会发现有对象更替,因而垃圾回收程序就不会那么频繁地运行
动态调配:
优化的一种极其模式。如果你的应用程序被垃圾回收重大地拖了后腿,能够利用它晋升性能。但这种状况并不多见。大多数状况下,这都属于过早优化,因而不必思考。