JavaScript 创建执行释放过程

一、对象创建过程

a. 内存分配

  • 当我们创建一个对象时(无论是通过构造函数还是字面量方式),JavaScript 引擎会在内存堆(Heap)中为这个对象分配空间。堆是一个用于存储复杂数据结构(如对象和数组)的区域。
// 创建对象并分配内存
var person = new Object();
person.name = 'Alice';
person.age = 30;

// 字面量方式创建对象并分配内存
var person = {
  name: 'Alice',
  age: 30
};

b. 构造函数调用

  • 如果使用 new 关键字调用构造函数来创建对象,引擎会先创建一个新的空对象,然后将该对象的原型指向构造函数的 prototype 属性,并将新对象作为上下文(this)执行构造函数内部的代码。
function Person(name, age) {
  this.name = name;
  this.age = age;
}

var alice = new Person('Alice', 30);

二、执行过程

a. 属性访问与方法调用

  • 在对象创建后,可以通过 .[] 操作符访问和修改其属性。
  • 可以调用对象的方法进行相关操作。

alice.sayHello = function() {
  console.log('Hello, my name is ' + this.name);
};

alice.sayHello(); // 输出:Hello, my name is Alice

b. 闭包与作用域链

  • 函数内部可以访问外部作用域中的变量,这种特性形成了闭包。当函数被调用时,它会形成自己的执行上下文,其中包含了作用域链,作用域链用于在当前作用域以及所有父级作用域中查找变量。
function outerFunction() {
  var outerVar = 'outer';

  function innerFunction() {
    console.log(outerVar); // 能够访问到outerVar,这是因为闭包的作用
  }

  innerFunction();
}

outerFunction();

三、释放过程

a. 垃圾回收机制

  • JavaScript 采用了自动垃圾回收机制,主要是基于可达性分析算法。简单来说,如果一个对象不再有任何引用指向它,那么这个对象就是不可达的,会被垃圾回收器视为垃圾并最终清理掉其所占用的内存资源。
var obj1 = { data: 'some value' };
var obj2 = obj1;

obj1 = null; // 现在只有obj2指向原对象
// 后续如果obj2也被设置为null或者超出作用域,则原对象成为不可达,会被GC回收

b. 循环引用问题

  • 当两个对象互相引用但没有其他引用指向它们时,尽管它们是不可达的,但由于互相引用导致垃圾回收器无法识别。现代浏览器和 Node. js 环境下的 V8 引擎已经实现了循环引用检测功能,但在某些情况下仍需注意避免造成循环引用。

总之,在 JavaScript 中,对象从创建到销毁的过程涉及内存管理、作用域规则以及垃圾回收策略等多个方面,理解这些概念对于编写高效且无内存泄漏的 JavaScript 代码至关重要。