JavaScript 原生值与引用值

摘要:在本教程中,您将学习 JavaScript 中两种不同类型的值,包括原生值和引用值。

JavaScript 有两种不同类型的值

  • 原生值
  • 引用值

原生值是数据的基本单元,而引用值是对象,可能包含多个值。

堆栈和堆内存

当您声明 变量 时,JavaScript 引擎会在两个内存位置分配内存:堆栈和堆。

静态数据是在编译时大小固定的数据。静态数据包括

由于静态数据的大小不会改变,JavaScript 引擎会为静态数据分配固定数量的内存空间,并将其存储在堆栈中。

例如,以下代码声明了两个变量,并将其值初始化为字面量字符串和数字

let name = 'John';
let age = 25;Code language: JavaScript (javascript)

由于 nameage 是原生值,JavaScript 引擎会将这些变量存储在堆栈中,如下图所示

请注意,字符串在许多编程语言中都是对象,包括 Java 和 C#。但是,在 JavaScript 中,字符串是原生值。

与堆栈不同,JavaScript 会将对象(和函数)存储在堆中。JavaScript 引擎不会为这些对象分配固定数量的内存。相反,它会根据需要分配更多空间。

以下示例定义了 nameageperson 变量

let name = 'John';
let age = 25;

let person = {
  name: 'John',
  age: 25,
};Code language: JavaScript (javascript)

在内部,JavaScript 引擎会分配内存,如下图所示

在这张图片中,JavaScript 为三个变量 nameageperson 分配了堆栈内存。

JavaScript 引擎在堆内存中创建了一个新对象。此外,它将堆栈内存中的 person 变量链接到堆内存中的对象。

因此,我们说 person 变量是一个引用,它引用了一个对象。

动态属性

引用值允许您随时添加、更改或删除属性。例如

let person = {
  name: 'John',
  age: 25,
};

// add the ssn property
person.ssn = '123-45-6789';

// change the name
person.name = 'John Doe';

// delete the age property
delete person.age;


console.log(person);Code language: JavaScript (javascript)

输出

{ name: 'John Doe', ssn: '123-45-6789' }Code language: CSS (css)

与引用值不同,原生值不能有属性。这意味着您不能向原生值添加属性。

JavaScript 允许您向原生值添加属性。但是,它不会产生任何效果。例如

let name = 'John';
name.alias = 'Knight';

console.log(name.alias); // undefined
Code language: JavaScript (javascript)

输出

undefinedCode language: JavaScript (javascript)

在此示例中,我们将 alias 属性添加到 name 原生值。但是,当我们通过 name 原生值访问 alias 属性时,它会返回 undefined

复制值

当您将一个变量的原生值赋值给另一个变量时,JavaScript 引擎会创建一个该值的副本,并将该副本赋值给该变量。例如

let age = 25;
let newAge = age;Code language: JavaScript (javascript)

在此示例中

  • 首先,声明一个名为 age 的新变量,并将其值初始化为 25
  • 其次,声明另一个名为 newAge 的变量,并将 age 赋值给 newAge 变量。

在幕后,JavaScript 引擎会创建原生值 25 的副本,并将该副本赋值给 newAge 变量。

下图说明了赋值后的堆栈内存

在堆栈内存中,newAgeage 是独立的变量。如果您更改一个变量的值,它不会影响另一个变量。

例如

let age = 25;
let newAge = age;

newAge = newAge + 1;
console.log(age, newAge);Code language: JavaScript (javascript)

当您将一个变量的引用值赋值给另一个变量时,JavaScript 引擎会创建一个引用,以便这两个变量都引用堆内存中的同一个对象。这意味着如果您更改一个变量,它会影响另一个变量。

例如

let person = {
  name: 'John',
  age: 25,
};

let member = person;

member.age = 26;

console.log(person);
console.log(member);Code language: JavaScript (javascript)

工作原理。

首先,声明一个名为 person 的变量,并将其值初始化为一个具有两个属性 nameage 的对象。

其次,将 person 变量赋值给 member 变量。在内存中,这两个变量都引用同一个对象,如下图所示

第三,通过 member 变量更改对象的 age 属性

由于 personmember 变量都引用同一个对象,因此通过 member 变量更改对象也会反映在 person 变量中。

总结

  • Javascript 有两种类型的值:原生值和引用值。
  • 您可以向引用值添加、更改或删除属性,而您无法对原生值执行此操作。
  • 从一个变量复制一个原生值到另一个变量会创建一个独立的值副本。这意味着更改一个变量中的值不会影响另一个变量。
  • 从一个变量复制一个引用到另一个变量会创建一个引用,以便两个变量都引用同一个对象。这意味着通过一个变量更改对象会反映在另一个变量中。
本教程是否有帮助?