定义变量就是申请一块内存空间,用于保存数据。
变量的使用
- 声明变量
- var 变量名
- 声明后其值为 undefined
- 变量赋值
- 变量名 = xxx
- 变量可以被重新赋值,新的值会覆盖原来的值
访问一个未被赋值的变量可以,但访问一个未声明的变量会报错。
JavaScript 允许不写 var 而直接赋值,这样就相当于给 window 的某个属性赋值。
标识符命名规范
在开发中凡是需要自行命名的位置,称为标识符。
变量提升
JS 中存在变量提升
- 所有的变量声明(赋值语句不会),会自动的提到代码的最顶部
- 但是,这种提升,不会超越脚本块
- JS 允许定义多个同名变量,但变量提升后会合并成一个
全局变量
JavaScript 大部分的宿主环境都会提供一个特殊对象,该对象可以直接在 JS 代码中访问,该对象叫做全局对象。
全局对象的属性可以直接使用,而不需要写上全局变量名。
在浏览器环境中,全局对象为 window。
通过 var 定义的变量,实际上会成为 window 对象的属性。
如果变量没有被赋值,则该变量不会覆盖 window 对象上的同名属性。
// window 对象有个属性是 name,所以
var name;
console.log(name); // 打印为空,而不是 undefined
// 定义了 name,又没有赋值,所以用的是 window.name 的值
// window.name 比较特殊,无论赋值什么,它都是字符串
name = undefined; // typeof name --> 'string'
name = null; // typeof name --> 'string'
console.log(name); // "null"
内存与变量存储
内存分为栈内存和堆内存,他们是内存的不同区域,不过它们的结构和存值方式都差不多。
引用名 -> [ 地址值 | 存储值 ]
堆和栈是两种不同的数据结构,我们可以简单的理解为,栈内存是内存中一片连续的区域,数据必须按内存地址顺序存放。而堆是内存中一个一个的块状区域,它不用非得按照内存地址顺序取用。
通常我们可以认为:
- 原始类型的变量,由栈内存储存,直接存放具体的值
- 引用类型的变量,由栈内存和堆内存共同储存
- 堆内存存放具体的对象的值
- 栈内存存放指向存放该对象的堆内存的首地址
⭐赋值行为与内存表现
1、变量重新赋值,并不是说覆盖原有的内存的值,而是新申请一块内存,写入新的值,并将引用名指向它。
2、变量间相互赋值,是让变量指向另一个变量所在的内存空间。
var a = 123; // 申请一块新的内存空间,引用名为 a,a -> [ 0x0001 | 123 ]
a = 456; // 申请一块新的内存空间,将 a 指向它,a -> [ 0x0002 | 456 ]
var b = a; // 引用名 b 也指向 a 指向的空间,b ->
// a -> [ 0x0002 | 456 ]
3、凡是出现对象字面量的位置,都一定会在堆内存中新申请一块空间存放,引用名在栈内存中指向这个新的地址。
var obj1 = { name: 'yu' };
var obj2 = { name: 'yu' };
obj1 == obj2 // false
⭐扩展
V8 引擎的垃圾回收器,会定期发现内存中再也无法访问到的对象,并标记为垃圾,之后垃圾回收器会在合适的时间将其占用的内存释放。
具体可看这篇文章:点击查看
其实并不是所有原始类型变量都放在栈内存 --- 解释函数闭包现象。
具体可看这篇文章:点击查看
写在最后
One day you'll leave this world behind.So live a life you will remember! --- Avicii
我是暮星,一枚有志于在前端领域证道的攻城狮。
优质前端内容持续输出中......,欢迎点赞 + 关注。