Skip to content

JS内存机制及参数传递 #4

Open
@L-small

Description

@L-small

变量的存放

  • 基本类型:保存在栈内存中,因为这些类型在内存中分别占有固定大小的空间,通过按值来访问。基本类型一共有6种:Undefined、Null、Boolean、Number 、String和Symbol
  • 引用类型:保存在堆内存中,因为这种值的大小不固定,因此不能把它们保存到栈内存中(影响查询效率),但内存地址大小的固定的,因此保存在堆内存中,在栈内存中存放的只是该对象的访问地址。当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。

image

在计算机的数据结构中,栈比堆的运算速度快,Object是一个复杂的结构且可以扩展:数组可扩充,对象可添加属性,都可以增删改查。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。所以查找引用类型值的时候先去栈查找再去堆查找。

复制变量值

  • 基本类型:在栈中新开一个字段,将值复制到新字段,新值和旧值是两个独立的字段,互不影响
  • 引用类型:在栈中新开一个字段,将对象在堆内存中的地址(引用)复制到新字段,新值和旧值指向堆内存中的同一个对象。
    当我们要复制对象时候,操作的是对象的引用。当给对象添加属性的时候,操作的是堆内存中实际的对象。

基本类型复制:
image

引用类型复制:
image

参数传递

  • 按值传递:传递的是实际参数的一个副本,这个值可能是基本类型,也可能是引用类型的地址.
  • 引用传递:传递的是实际参数的地址的一个副本

函数参数的传递实际上就是变量的复制。JS中所有的函数参数都是按值传递。引用类型的传递也只不过是按值传递,传递的是"引用地址"指针的值(栈内存中指针的地址)。

例:

function changeStuff(a, b, c) {
  a = a * 10; // 对 a 赋值,修改 a 的指向,新的值是 a * 10
  b.item = "changed"; // 因为 b 与 obj1 指向同一个对象,所以这里会修改原始对象 obj1.item 的内容
  c = {item: "changed"}; // 对 c 重新赋值,修改 c 的指向,其指向的对象内容是 {item: "changed"}
}

变量初始化

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

image

调用函数

changeStuff(num, obj1, obj2);

image

执行函数体

a = a * 10;
b.item = "changed";
c = {item: "changed"};

image

例2:

function setName(obj){
  obj.name = 'zhangsan';
  obj = new Object();   // 重写obj时,obj的变量引用就是一个局部对象了,函数执行完后就销毁了
  obj.name = 'lisi';
}

var person = new Object();
setName(person);
person.name;     // zhangsan

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions