
JavaScript中有一些您作为开发人员可能不知道的主题。了解这些主题可以帮助您编写更好的代码。其中包括内存生命周期、堆、栈和调用栈。在本教程中,您将了解这些主题以及JavaScript的工作原理。
JavaScript是一种非常宽容的编程语言。它允许你以多种方式做很多事情。它也为你做了很多工作。内存管理就是其中之一。问问你自己:多少次你不得不考虑为你的变量或函数分配内存?
当你不再需要那些变量或函数时,你需要考虑释放这些内存多少次?机会不止一次。这同样适用于了解堆、堆栈和调用堆栈的工作方式,或者它到底是什么。然而,您仍然可以使用JavaScript。您仍然可以编写每天都能工作的代码。
这些事情你不必知道。它们也不是必需的。但是,了解它们以及它们如何工作可以帮助您理解JavaScript是如何工作的。反过来,这可以帮助您编写更好的代码,成为更好的JavaScript。
记忆的生命周期
让我们从最简单的部分开始。什么是内存生命周期,它是关于什么的,它是如何在JavaScript中工作的?内存生命周期是指编程语言如何使用内存。无论哪种语言,内存的生命周期几乎总是相同的。它由三个步骤组成。
第一步是内存分配。当您分配一个变量或创建一个函数或对象时,必须为它分配一定数量的内存。第二步是内存使用。当您使用代码中的数据进行读或写操作时,您使用的是内存。从变量中读取或改变值就是从内存中读取和写入内存。
第三步是释放记忆。当你不再使用某个函数或对象时,内存就会被释放。一旦释放,就可以再次使用。这就是对内存生命周期的概括。JavaScript的优点是它为您实现了这三个步骤。
JavaScript根据需要分配内存。它使您更容易处理分配的内存。最后,它还能起重和清理所有的脏乱。它使用垃圾收集来持续检查内存,并在不再使用时释放内存。结果呢?
作为一名JavaScript开发人员,您不必担心为变量或函数分配内存。在读取之前,您也不必担心选择正确的内存地址。而且,你不必担心释放你过去使用过的内存。
堆栈和内存堆
现在您已经了解了内存生命周期的各个步骤。你知道内存的分配,使用和释放。你可能会问,这些变量、函数和对象实际存储在哪里?答案是:视情况而定。JavaScript不会将所有这些东西存储在同一个地方。
相反,JavaScript使用了两个位置。这些位置是堆栈和内存堆。将使用这些位置中的哪一个取决于您当前正在使用的内容。
堆栈
堆栈是JavaScript仅用于存储静态数据的地方。这包括基本数据类型值。例如,数字、字符串、布尔值、未定义和null。这些静态数据还包括引用。这些引用指向您创建的对象和函数。
这些数据有一个共同点。这些数据的大小是固定的,JavaScript在编译时就知道这个大小。这也意味着JavaScript知道它应该分配多少内存,并分配这个数量。这种类型的内存分配称为“静态内存分配”。它发生在代码执行之前。
关于静态数据和内存,有一点很重要。这些原始值的大小是有限制的。对于堆栈本身也是如此。这也有局限性。这些限制有多高取决于特定的浏览器和引擎。
内存堆
JavaScript存储数据的第二个地方是内存堆。这种存储更加动态。当涉及到内存堆时,JavaScript并不分配固定数量的内存。相反,它在需要的时候分配内存。这种类型的内存分配被称为“动态内存分配”。
哪些数据存储在内存堆中?堆栈是JavaScript存储静态数据的地方,而内存堆是JavaScript存储对象和函数的地方。记住,使用原语创建时,使用的是静态数据。JavaScript将这些静态数据存储在堆栈中。
这些数据总是固定分配内存。另一方面,当您创建对象或函数时,JavaScript将它们存储在内存堆中。为这些分配的内存不是固定的。它是根据需要动态分配的。
当您创建一个变量并为它赋值时,它将存储在堆栈中。当你做同样的尝试时,会发生一些不同的事情,但是是针对一个对象。如果您声明一个变量并为它分配一个对象,将会发生两件事。首先,JavaScript将在堆栈中为该变量分配内存。
当涉及到对象本身时,JavaScript将把它存储在内存堆中。存在于堆栈中的那个变量将只指向内存堆中的这个对象。该变量将是对该对象的引用。您可以将引用看作是现有事物的快捷方式或别名。
这些参考不是那些东西本身。它们只是那些“真实”事物的链接。您可以使用这些链接来访问它们引用(它们链接到)的内容并对其进行操作。
复制对象和原语
这也是为什么在JavaScript中创建对象副本并不是那么简单的原因。试图通过引用来创建存储在变量中的对象的副本不会创建真正的副本。它不会复制对象本身。它只复制引用那个对象。这叫做浅拷贝。
当您更改原始对象时,副本也将更改。这是因为仍然只有一个对象。但是,对那个对象有两个引用(别名或链接)。当您使用其中一个引用来更改对象时,另一个引用仍然指向相同的对象,即您刚刚更改的对象。
当您尝试复制原始值时,这将不会发生。当您尝试复制原始值,并且更改了原始值时,副本将保持不变。原因是:没有参考资料。您正在创建真正的副本,并直接使用这些副本。
您可能已经听说过所谓的“调用堆栈”。这与我们之前在本教程中讨论的堆栈不同。如您所知,堆栈是JavaScript用来存储用原始值赋值的变量的地方。调用堆栈是不同的。
调用堆栈是JavaScript用来跟踪函数的一种机制。当您调用一个函数时,JavaScript会将该函数添加到调用堆栈中。如果该函数调用另一个函数,JavaScript也会将该函数添加到调用堆栈中,位于第一个函数之上。
这个过程将对上一个函数调用的任何其他函数重复。当一个函数完成时,JavaScript将从调用堆栈中删除该函数。有两件重要的事情。第一件事是堆栈中的每个新函数都将被添加到调用堆栈的顶部。
第二件事是调用堆栈从上到下执行。添加到堆栈的最后一个函数将作为first执行。添加到堆栈的第一个函数将最后执行。这也被称为后进先出原则。让我们用一个简单示例的代码来说明这一点。
总结:JavaScript中的内存生命周期、堆、栈和调用栈
内存生命周期、堆、堆栈和调用堆栈是不经常讨论的主题。没有太多的材料可以用来更多地了解它们。我希望本教程能帮助您理解内存生命周期、堆、堆栈和调用堆栈是什么,以及它们是如何工作的。
如果你喜欢这篇文章,请订阅,这样你就不会错过任何未来的帖子。
