JavaScript pass

2025 年 3 月 3 日 | 阅读 6 分钟

JavaScript 是 Web 开发的关键组成部分,以其适应性和动态性而闻名。理解用于在函数之间传递变量的“按值传递”和“按引用传递”过程是 JavaScript 编程的基本组成部分。尽管这些过程是 JavaScript 行为的基础,但开发人员有时会发现它们令人困惑和具有挑战性。

值传递

JavaScript 中“按值传递”的核心思想控制着基本数据类型作为参数传递给函数时的处理方式。理解此机制对于编写可靠且一致的代码至关重要。

当基本数据类型(例如字符串、整数或布尔值)作为参数传递给函数时,它们是“按值传递”的。当值“按值传递”时,会创建一个原始值的副本并将其发送到函数,而不是传递对原始变量的引用。因此,在函数作用域内对参数所做的更改不会影响最初在函数外部输入的值。

看这个例子

JavaScript 代码

输出

100

这里有一个名为“value”的参数被发送到“doubleTheValue()”函数,该函数将其值加倍。当我们以“number”作为参数调用“doubleTheValue()”时,“number”的初始值不会改变。这种行为是因为“number”是通过值传递给函数的。由于“value”是方法内部值 5 的一个独立副本,因此对“value”所做的修改不会影响“number”的初始值。

当在函数作用域内进行修改时,按值传递可确保函数边界之外的变量不会意外丢失其原始值。它提供了一定程度的数据封装,并有助于避免不必要的副作用。

按值传递的基本值也赋予了它们不可更改的特性,因为在 JavaScript 中,它们被认为是不可更改的。一旦将变量的原始值分配给它,就不能更改。在某些特定方法中,变量的值可能会被破坏。任何被称为测量值的操作只会预先执行相同事物的新值,并且旧值保持不变。

基本上,JavaScript 代码是可读、一致和可维护的。规则的操作高度依赖于值是按值传递还是按引用传递。开发人员可以通过理解不采用任何模板或结构并作为参数发送到方法的元素的工作方式,来确保他们的代码正常工作,并且不会产生任何不可预测和不需要的后果。

考虑另一个例子

JavaScript 代码

输出

100

在这种情况下,即使在“modifyTheValue()”函数内部更新了“value”参数,函数外部的“number”的初始值仍保持不变。这种行为的原因是 JavaScript 的原始值是不可变的。

引用传递

“按引用传递”是 JavaScript 的基本思想之一,它指定了函数如何处理作为参数提供的复杂数据类型(如对象和数组)。理解此技术对于编写可靠且高效的代码至关重要,尤其是在处理可变数据结构时。

函数通过引用接收传递给它的对象或数组。这表明对原始数据结构的引用被提供给函数,而不是创建对象或数组的新副本。因此,在函数作用域内对对象或数组所做的更改会立即影响函数外部的原始数据结构。

看这个例子

JavaScript 代码

输出

{
existingProperty: "Existing_Number", 
newProperty: "New_Number"
}

此示例中的“addAProperty()”函数通过接受一个名为“object”的对象作为参数,向其添加一个名为“newProperty”的新属性。当以“MySampleObject”作为参数调用“addAProperty()”时,“MySampleObject”是原始对象,它被更改为包含新属性。这是因为函数通过引用接收“mySampleObject”。由于在方法内部,“object”和“mySampleObject”都指向相同的内存位置,因此对“object”所做的修改也会影响“mySampleObject”。

此方法可以避免复制大型数据结构或包。因此,处理复杂操作的效率更高。另一种方法是函数可以直接使用原始数据结构,这样它们可以更好地利用内存,从而更有效地完成工作。

然而,按引用传递也带来了可能出现意外结果的令人失望之处。必须监视所有更改,否则函数有能力重塑输入数据结构,从而导致更改后的输出。一方面,这在函数可能相互依赖并共享数据的大型代码库中确实如此。

此外,作为引用值的参数侧重于不变性;因为 JavaScript 在对象和数组中具有可变属性。通过引用传递的对象或数组所做的修改是不可逆的,并且可能会影响使用相同数据结构的程序片段。

在 JavaScript 中进行熟练的数据管理和操作需要理解按引用传递。开发人员可以通过理解复杂数据类型作为参数传递时的处理方式,来使用按引用传递设计高效代码,同时注意潜在的副作用并保护数据完整性。

按值传递和按引用传递的区别

函数上数据处理和函数更改方式的差异是区分按值传递和其他方式的关键参数。

必须确保函数作用域内的状态未改变(未更改),并且只有函数边界之外的原始值才能更改,这需要保留原始值。此外,它通过提供数据封装来防止不必要的副作用,从而简化了过程。

当按引用传递时,函数可能会警惕地持有原始对象或数组,而按值传递只获取对初始数据结构的引用。由于这个事实,数据的突变需要彻底控制,并且意外不良结果的可能性会增加,但这可能会提高内存效率。

选择最佳方法

在编写 JavaScript 代码时,重要的是要问自己哪种方法更适合手头的任务:通过引用封装复杂数据类型,以便快速修改大型对象或数组,并将更新传播到程序的各个部分,同时通过值传递基本数据类型,以确保原始值保持不变并防止意外修改。

要考虑的性能方面

由于使用按值传递时会创建副本,因此开销可能会略有增加,尤其是在较大的数据结构中。相反,按引用传递可以提供卓越的速度和内存效率,因为它不会产生重复数据的开销。

可变数据与不可变数据

由于 JavaScript 中的原始数据类型是通过值传输的,因此它们是不可变的,这意味着一旦分配,它们的值就无法更改。它的不变性增强了数据完整性,这保证了原始值不会改变。另一方面,通过引用传递的复杂数据类型是可变的,并且允许对原始数据结构进行更改。这些数据类型的示例是对象和数组。但是,如果处理不当,其可变性会带来意外不良后果的风险。

内存管理

对于按值传递槽,通常会发生的事情之一是在内存中完全创建另一个槽。这可能会导致单元的内存使用量增加,例如对于复杂的数据结构。

创建数据副本

当您需要对复杂数据结构进行更改而不影响原始结构时,您可以选择创建对象的浅拷贝或深拷贝,或数组。尽管保留了对更深层对象或数组的引用,但浅拷贝会复制数据的顶层结构。

结论

编写可靠且无错误的 JavaScript 代码需要理解按值传递和按引用传递。通过了解如何将各种数据类型提供给函数,您可以预测函数内部所做的更改将如何影响原始值。请记住,对象和数组是通过引用提供的,而原始数据类型是通过值传递的。利用这些知识,您可以编写更可靠、更高效的 JavaScript 代码。