摘要:在本教程中,您将学习 JavaScript 中两种不同类型的值,包括原生值和引用值。
JavaScript 有两种不同类型的值
- 原生值
- 引用值
原生值是数据的基本单元,而引用值是对象,可能包含多个值。
堆栈和堆内存
当您声明 变量 时,JavaScript 引擎会在两个内存位置分配内存:堆栈和堆。
静态数据是在编译时大小固定的数据。静态数据包括
由于静态数据的大小不会改变,JavaScript 引擎会为静态数据分配固定数量的内存空间,并将其存储在堆栈中。
例如,以下代码声明了两个变量,并将其值初始化为字面量字符串和数字
let name = 'John';
let age = 25;
Code language: JavaScript (javascript)
由于 name
和 age
是原生值,JavaScript 引擎会将这些变量存储在堆栈中,如下图所示
请注意,字符串在许多编程语言中都是对象,包括 Java 和 C#。但是,在 JavaScript 中,字符串是原生值。
与堆栈不同,JavaScript 会将对象(和函数)存储在堆中。JavaScript 引擎不会为这些对象分配固定数量的内存。相反,它会根据需要分配更多空间。
以下示例定义了 name
、age
和 person
变量
let name = 'John';
let age = 25;
let person = {
name: 'John',
age: 25,
};
Code language: JavaScript (javascript)
在内部,JavaScript 引擎会分配内存,如下图所示
在这张图片中,JavaScript 为三个变量 name
、age
和 person
分配了堆栈内存。
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)
输出
undefined
Code 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
变量。
下图说明了赋值后的堆栈内存
在堆栈内存中,newAge
和 age
是独立的变量。如果您更改一个变量的值,它不会影响另一个变量。
例如
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
的变量,并将其值初始化为一个具有两个属性 name
和 age
的对象。
其次,将 person
变量赋值给 member
变量。在内存中,这两个变量都引用同一个对象,如下图所示
第三,通过 member
变量更改对象的 age
属性
由于 person
和 member
变量都引用同一个对象,因此通过 member
变量更改对象也会反映在 person
变量中。
总结
- Javascript 有两种类型的值:原生值和引用值。
- 您可以向引用值添加、更改或删除属性,而您无法对原生值执行此操作。
- 从一个变量复制一个原生值到另一个变量会创建一个独立的值副本。这意味着更改一个变量中的值不会影响另一个变量。
- 从一个变量复制一个引用到另一个变量会创建一个引用,以便两个变量都引用同一个对象。这意味着通过一个变量更改对象会反映在另一个变量中。