推荐的最佳实践
- 初始化变量之前一定要先声明变量 — 推荐使用let const
- 访问局部变量比访问全局变量要快
-
原始值和引用值
原始值:Undefined、Null、Boolean、Number、String 和 Symbol。保存原始值的变量是按值
- 对象: 保存引用值的变量是按引用
属性的添加:原始值不能有属性,尝试给原始值添加属性不会报错,但是会得到undefined,也就是添加失败。只有引用值可以添加属性。
let name = "Nicholas";
name.age = 27;
console.log(name.age); // undefine
在赋值时: 值的贮存是完全独立的,赋值后可以独立使用。引用的赋值,是赋值指针,会指向同一个位置。
let obj1 = new Object();
let obj2 = obj1;
obj1.name = "Nicholas";
console.log(obj2.name); // "Nicholas"
在传递参数时:值会被赋值到一个局部变量中。传递参数的时候,引用也是按值传递的。 (函数的参数就是局部变量,所以是单独的一个变量)
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
let person = new Object();
setName(person);
console.log(person.name); // "Nicholas" , 这里的obj.name,并没有是"Greg"
确定类型时:值用typeof就可以判断,对象需要用instanceof,判断是否是那个对象的实例,值使用instanceof会始终返回false;
上下文和作用域
上下文决定了,在哪里可以使用变量活动对象。
- 函数有单独的上下文,在函数执行的时候,进入到函数上下文栈中,结束后弹出当前上下文,回到之前的上下文。 函数参数被认为是当前上下文中的变量
- 声明变量使用const let
- 标识符查找,从内向外, 所以: 访问局部变量比访问全局变量要快
垃圾回收
确定哪个变量不会再 使用,然后释放它占用的内存, 是js语言自动执行的,一般使用标记清理和引用计数这两种策略。常用策略:标记清理
标记清理
- 如果数据不再必要,那么把它设置为 null,从而释放其引用。这也可以叫作解除引用。这个建议最适合全局变量和全局对象的属性
- 使用const 和 let 在专属的块中使用,可以更快的触发垃圾回收
- 减少隐藏类的生成 —- 删除和动态赋值属性会产生隐藏类。所以最好使用null进行解除引用。并且一开始就声明好类中的属性。
- 内存泄露: 意外声明全局变量,定时器产生的闭包,闭包 —- 容易产生内存泄露
- 静态分配与对象池 —- 不推荐使用