-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 83 题:var、let 和 const 区别的实现原理是什么 #133
Comments
先说说这三者的区别吧:
然后是原理,原理确实没认真研究过,在网上翻了一番资料,结合自己的理解简单说下(纯属个人愚见,高手轻喷):变量与内存之间的关系,主要由三个部分组成:
JS 引擎在读取变量时,先找到变量绑定的内存地址,然后找到地址所指向的内存空间,最后读取其中的内容。当变量改变时,JS 引擎不会用新值覆盖之前旧值的内存空间(虽然从写代码的角度来看,确实像是被覆盖掉了),而是重新分配一个新的内存空间来存储新值,并将新的内存地址与变量进行绑定,JS 引擎会在合适的时机进行 GC,回收旧的内存空间。 const 定义变量(常量)后,变量名与内存地址之间建立了一种不可变的绑定关系,阻隔变量地址被改变,当 const 定义的变量进行重新赋值时,根据前面的论述,JS 引擎会尝试重新分配新的内存空间,所以会被拒绝,便会抛出异常。 坐等高手答疑。 |
一、实现原理(一)、var的实现原理(二)、let的实现原理(三)、const的实现原理
二、应用场景(一)var应用场景(二)let应用场景
(三)const应用场景三、var、let、const的区别(一)var
(二)let
(三)const
四、参考文章
|
针对区别做了总结,实现原理属于推测,求真相。 |
比如解析如下代码步骤: {
// 没用的第一行
// 没用的第二行
console.log(a) // 如果此时访问a报错 a is not defined
let a = 1
} 步骤:
对比于var,let、const只是解耦了声明和初始化的过程,var是在任何语句执行前都已经完成了声明和初始化,let、const仅仅是在任何语句执行前只完成了声明 |
搬运: |
变量被重新覆盖之后,之前的内存地址和内存空间,会被垃圾回收机制回收的吧! |
var的话会直接在栈内存里预分配内存空间,然后等到实际语句执行的时候,再存储对应的变量,如果传的是引用类型,那么会在堆内存里开辟一个内存空间存储实际内容,栈内存会存储一个指向堆内存的指针 let的话,是不会在栈内存里预分配内存空间,而且在栈内存分配变量时,做一个检查,如果已经有相同变量名存在就会报错 const的话,也不会预分配内存空间,在栈内存分配变量时也会做同样的检查。不过const存储的变量是不可修改的,对于基本类型来说你无法修改定义的值,对于引用类型来说你无法修改栈内存里分配的指针,但是你可以修改指针指向的对象里面的属性 |
let const 和var三者都会存在变量提升
|
咋回事咧?这么明显的错误~// 暂时性死区了兄弟 Cannot access 'a' before initialization
console.log(a)
let a = 1;
// is not defined 是未定义
console.log(temp); // 此时temp还未定义。 |
转载: 我们就从声明过程,内存分配,和变量提升这三点来看这三者之间的区别。 一.声明过程 { 发现作用域有let a,先注册个a,仅仅注册 二.内存分配 let,是不会在栈内存里预分配内存空间,而且在栈内存分配变量时,做一个检查,如果已经有相同变量名存在就会报错 const,也不会预分配内存空间,在栈内存分配变量时也会做同样的检查。不过const存储的变量是不可修改的,对于基本类型来说你无法修改定义的值,对于引用类型来说你无法修改栈内存里分配的指针,但是你可以修改指针指向的对象里面的属性 三.变量提升 let只是创建过程提升,初始化过程并没有提升,所以会产生暂时性死区。 |
怎么感觉大家回答的都是表层的东西...栈和堆这些都知道哪个可改变哪个不可改变...问的应该是怎么做到不可改变的吧? |
其实题目想要考察的就是 javascript 表面语义的东西。 |
明白了 十分感谢解惑 因为总觉得这样回答似乎很简单 看来是我想复杂了 |
并且可能非常多前端开发者对于计算基础的知识并不牢靠。比如什么是栈和堆?操作系统的栈和堆概念和编程语言的栈、堆概念一致吗(一般我们了解程序的堆栈概念来自于 C 语言)?和传统的数据结构中的栈结构和二叉堆又有什么关联呢?等等这些概念。 |
function foo() {
var a = 1;
let b = 2;
} 我的理解: 等到execute phase阶段,a赋值为1,b赋值为2,就没什么可说的了。 另外块级作用域也是因为通过不同方式声明的变量被赋值到不同的EnvironmentRecord,LexicalEnvironment和VariableEnvironment的区别,在一个方法内部,每一个块级代码都会新生成一个LexicalEnvironment,并保留上一个LexicalEnvironment的引用,但是一个方法内只有一个VariableEnvironment。 |
var 存在变量提升, let const 声明的变量不会
|
|
在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出 |
const 实现 |
var let const 都存在变量提升,而且都初始化为undefined,这个可以在浏览器控制台debugger Scope的Local中看到三者都是undefined。
|
|
var,已废弃
let/const,更现代
|
var let const |
var:
let/const:
let:
const:
|
No description provided.
The text was updated successfully, but these errors were encountered: