JavaScript基础之变量、作用域与内存

108 阅读3分钟

变量、作用域与内存

原始值与引用值

  • 原始值:简单的数据。 Undefined、Null、Boolean、Number、String、Symbol。保存原始值的变量是按值访问。
  • 引用值:由多个值构成的对象。引用值是保存在内存中的对象。保存引用值的变量是按引用访问。

动态属性

只有引用值才可以动态添加属性

复制值

原始值复制

let num1 = 5
let num2 = num1

引用值复制

let obj1 = new Object();
obj1.name = 'Nicholas'
console.log(obj2.name) // 'Nicholas'
let obj2 = obj1

传递参数

原始值传递

function addTen(num) {
  num += 10
  return num
}
let count = 20
let result = addTen(count)
console.log(count) // 20
console.log(result) // 30

引用值传递

function setName(obj) {
  obj.name = 'Nicholas'
}
let person = new Object()
setName(person)
console.log(person.name) // 'Nicholas'

此时,obj和person都指向同一个对象。

确定类型

  • typeof:判断一个变量是否为原始类型
let s = 'Nicholas'
let b = true;
let i = 22;
let u;
let n = null;
let o = new Object();

console.log(typeof s); // string
console.log(typeof b); // number
console.log(typeof i); // boolean
console.log(typeof u); // undefined
console.log(typeof n); // object
console.log(typeof o); // object
  • instanceof:判断引用类型变量属于哪一个类型的对象
console.log(person instanceof Object); // 变量person是Object吗?
console.log(colors instanceof Array); // 变量colors是Array吗?

执行上下文与作用域

执行上下文:变量或函数的上下文决定了它们可以访问那些数据,以及它们的行为。每一个上下文都有一个关联的变量对象(variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。

  • 全局上下文:在浏览器中,全局上下文代表的是window对象,因此所有通过var定义的全局变量和函数都会成为window对象的属性和方法,但使用let、const的声明不会定义在全局上下文中。全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器
  • 作用域链:作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。

作用域增强

执行上下文主要有全局上下文和函数上下文,但可以通过try/catch语句的catch块、with语句这两种情况下,都会在作用域链前端添加指定的对象。

变量声明

  1. 使用var的函数作用域声明
  • 变量未初始化时,使用var声明变量,变量会被自动添加到最接近的上下文。
  • 变量未经声明就被初始化了,那么它就会被自动添加到全局上下文。
  1. 使用let的块级作用域声明
  • 块级作用域由最近的一对包含花括号{}界定。话句话说,if块、while块、function块,甚至连单独的块也是let声明变量的作用域。
  • 严格来讲,let在javaScript运行时中也会被提升,但由于‘暂时性死区’的缘故,实际上不能声明之前使用let变量。
  1. 使用const的常量声明
  • 使用const声明的变量必须同时初始化为某个值。
  • 一经声明,在其生命周期的任何时候都不能在重新赋予新值。
const a; // SyntaxError: 常量声明时没有初始化
const b = 3;
console.log(b); // 3
b = 4; // TypeError:给常量赋值
  • 其他方面与let声明一样

垃圾回收

javaScript是使用垃圾回收的语言,也就是说执行环境负责在代码执行时管理内存,通过自动内存管理实现内存分配和闲置资源回收。

  1. 垃圾回收策略:
  • 标记清理(常用)
  • 引用计数
  1. 性能优化:

将内存占用量保持在一个较小的值可以让页面性能更好,优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不在必要,那么把它设置为null,从而释放其引用。

  • 通过const和let声明提升性能
  • 隐藏类和删除操作
  • 内存泄漏(windows对象上创建属性、定时器未清除)
  • 不要动态创建矢量对象