原始值与参考值

2024-05-25

我读过一本名为“Web 开发人员的专业 Javascript”的书,其中写道:“变量由引用值或原始值分配。引用值是存储在内存中的对象”。然后它没有提到原始值是如何存储的。所以我猜它没有存储在内存中。基于此,当我有这样的脚本时:

var foo = 123;

JavaScript 如何记住foo变量供以后使用?


好吧,想象你的变量是一张纸——一张便签纸。

Note 1: A variable is a 便利贴.

现在,便利贴非常小。你只能在上面写一点点信息。如果您想写更多信息,则需要更多便签纸,但这不是问题。想象一下,您有无穷无尽的便利贴。

Note 2:你有一个endless供应便签纸,哪家店少量的信息。

太好了,你可以在便利贴上写什么?我可以写:

  1. 是或否(aboolean).
  2. 我的年龄(一number).
  3. 我的名字(一string).
  4. 什么都没有(不明确的).
  5. 涂鸦或其他任何对我来说毫无意义的东西(null).

所以我们可以写一些简单的东西(让我们居高临下地称它们为原始的东西)在我们的便利贴上。

Note 3:你可以写原始便利贴上的东西。

所以说我写30贴在便利贴上,提醒自己为今晚在我家举办的小型聚会买 30 片奶酪(我的朋友很少)。

当我去把便条贴在冰箱上时,我看到我妻子在冰箱上贴了另一张便条纸,上面还写着30(提醒我她的生日是这个月30号)。

Q:两张便签传达的信息是否相同?

A:是的,他们都说30。我们不知道是 30 片奶酪还是每月 30 日,坦率地说,我们不在乎。对于一个不太了解的人来说,这都是一样的。

var slicesOfCheese = 30;
var wifesBirthdate = 30;

alert(slicesOfCheese === wifesBirthdate); // true

Note 4:两张写有相同内容的便签传达了相同的信息,即使它们是两张不同的便签。

今晚我真的很兴奋——和老朋友一起出去玩,玩得很开心。然后我的一些朋友打电话给我说他们无法参加聚会。

所以我走到冰箱前把上面的东西擦掉30在我的便利贴上(不是我妻子的便利贴 - 这会让她非常生气)并将其设为20.

Note 5:您可以擦除便利贴上写的内容并写其他内容。

Q:这一切都很好,但如果我的妻子想写一份杂货清单,供我在我出去买奶酪时挑选,该怎么办?她需要为每件物品都写一张便利贴吗?

A:不,她会拿一张长长的纸单,然后在纸上写下杂货清单。然后她会写一张便利贴告诉我在哪里可以找到杂货清单。

那么这里发生了什么?

  1. 杂货清单显然不是simple(呃...原始) data.
  2. 我妻子把它写在一张较长的纸上。
  3. 她在便利贴上写下了在哪里可以找到它。

亲爱的,杂货清单就在你的键盘下面。

回顾一下:

  1. 实际的对象(杂货列表)位于我的键盘下方。
  2. 便利贴告诉我在哪里可以找到它(对象的地址)。

Note 6:引用值是对对象的引用(可以找到它们的地址)。

Q:我们怎么知道两张便签纸说的是同一件事?假设我的妻子又制作了一份购物清单,以防我把第一份清单放错地方,并为其写了另一张便利贴。两个列表都说同样的事情,但是便利贴说的是同样的事情吗?

A:不。第一个便签告诉我们在哪里可以找到第一个列表。第二个告诉我们在哪里可以找到第二个列表。两个列表是否说的是同一件事并不重要。它们是两个不同的列表。

var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];

alert(groceryList1 === groceryList2); // false

Note 7:仅当两个便签引用同一对象时,它们才传达相同的信息。

这意味着,如果我的妻子制作了两张便签来提醒我购物清单在哪里,那么这两张便签包含相同的信息。所以这:

亲爱的,杂货清单就在你的键盘下面。

包含与以下内容相同的信息:

不要忘记杂货清单就在键盘下方。

用编程术语来说:

var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = groceryList1;

alert(groceryList1 === groceryList2); // true

这就是您需要了解的全部内容原语 and 参考在 JavaScript 中。无需陷入类似的事情heap和动态内存分配。如果您使用 C/C++ 进行编程,这一点很重要。

Edit 1:哦,重要的是,当你传递变量时,你实际上是在传递原始 values by value and 参考 values 引用.

这只是一种复杂的说法,即您将一张便利贴上写的所有内容复制到另一张便利贴上(无论您是否复制原始值或一个参考).

复制引用时,被引用的对象不会移动(例如,我妻子的杂货清单将始终保留在我的键盘下,但我可以将复制的便签带到任何我想要的地方 - 原始的便签仍将位于冰箱上)。

Edit 2:回应 @LacViet 发表的评论:

首先,我们讨论的是 JavaScript,而 JavaScript 没有stack or a heap。它是一种动态语言,JavaScript 中的所有变量都是动态的。为了解释差异,我将其与 C 进行比较。

考虑以下 C 程序:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    printf("%d", c);
    return 0;
}

当我们编译这个程序时,我们得到一个可执行文件。可执行文件被分为多个段(或部分)。这些段包括堆栈段、代码段、数据段、额外段等。

  1. 堆栈段用于存储调用函数或中断处理程序时程序的状态。例如,当函数f调用函数g然后是功能状态f(当时寄存器中的所有值)保存在堆栈中。什么时候g将控制权返回给f然后这些值被恢复。
  2. 代码段保存处理器要执行的实际代码。它包含处理器必须执行的一堆指令,例如add eax, ebx (where add是操作码,并且eax & ebx是参数)。该指令添加寄存器的内容eax and ebx并将结果存储在寄存器中eax.
  3. 数据段用于为变量保留空间。例如,在上面的程序中,我们需要为整数预留空间a, b and c。另外,我们还需要为字符串常量预留空间"%d"。因此,保留的变量在内存中具有固定地址(在链接和加载之后)。
  4. 除了所有这些之外,操作系统还为您提供了一些额外的空间。这称为堆。您需要的任何额外内存都是从此空间分配的。以这种方式分配的内存称为动态内存。

让我们看一个具有动态内存的程序:

#include <stdio.h>
#include <malloc.h>

int main() {
    int * a = malloc(3 * sizeof(int));

    a[0] = 3;
    a[1] = 5;
    a[2] = 7;

    printf("a: %d\nb: %d\nc: %d\n", a[0], a[1], a[2]);

    return 0;
}

因为我们想要动态分配内存,所以需要使用指针。这是因为我们想要使用相同的变量来指向任意内存位置(不一定每次都是相同的内存位置)。

所以我们创建一个int指针(int *)称为a。的空间a从数据段分配(即它不是动态的)。然后我们打电话malloc从堆中为 3 个整数分配连续空间。第一个内存地址int返回并存储在指针中a.

Q:我们学到了什么?

A:为所有变量分配固定数量的空间。每个变量都有一个固定的地址。我们还可以从堆中分配额外的内存,并将该额外内存的地址存储在指针中。这称为动态内存方案。

从概念上讲,这类似于我对变量作为便签的解释。所有变量(包括指针都是便签)。然而,指针很特殊,因为它们引用内存位置(就像引用 JavaScript 中的对象)。

然而,相似之处就到此为止。以下是差异:

  1. 在C中一切都是按值传递(包括指针中的地址)。到传递一个参考您需要通过指针使用间接寻址。 JavaScript 仅按值传递基元。传递引用由引擎透明地处理,就像传递任何其他变量一样。
  2. 在 C 中,您可以创建一个指向原始数据类型的指针,例如int。在 JavaScript 中,您无法创建对原始值的引用,例如number。所有原语始终按值存储。
  3. 在 C 中,您可以对指针执行各种操作。这称为指针算术。 JavaScript 没有指针。它只有参考。因此您无法执行任何指针算术。

除了这三个之外,C 和 JavaScript 之间最大的区别是 JavaScript 中的所有变量实际上都是指针。因为 JavaScript 是一种动态语言,所以可以使用相同的变量来存储number and a string在不同的时间点。

JavaScript是一种解释性语言,解释器通常用C++编写。因此,JavaScript 中的所有变量都映射到宿主语言中的对象(甚至是原语)。

当我们在 JavaScript 中声明一个变量时,解释器会为其创建一个新的通用变量。然后,当我们为其分配一个值(无论是原语还是引用)时,解释器只需为其分配一个新对象。在内部,它知道哪些对象是原始对象,哪些是实际对象。

从概念上讲,这就像做这样的事情:

JSGenericObject ten = new JSNumber(10); // var ten = 10;

Q:这是什么意思?

A:这意味着 JavaScript 中的所有值(基元和对象)都是从堆中分配的。甚至变量本身也是从堆中分配的。认为基元是从堆栈中分配而只有对象是从堆中分配的说法是错误的。这是C和JavaScript之间最大的区别。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

原始值与参考值 的相关文章

随机推荐

  • 如何在 PySpark 中累计聚合一天内超过“1 小时”的窗口

    我有一个如下所示的 Spark DataFrame group id event time XXXX 2017 10 25 14 47 02 717013 XXXX 2017 10 25 14 47 25 444979 XXXX 2017
  • 如何创建粗体 UIFont

    我正在我的表格视图中进行一些自动换行 因为某些值太大 以至于超出了屏幕边缘 但是 字体 大小和粗体与表视图的默认设置不匹配 希望有人能帮助我解决这个问题 这就是我正在做的设置字段的操作 CGFloat tableView UITableVi
  • 如何实现类似于@Override java注解的东西?

    有了这个jdk代码 java lang Override java package java lang import java lang annotation Target ElementType METHOD Retention Rete
  • c# .NET MVC 4 - 如何创建使用 Ninject 服务的 Quartz 作业?

    我正在使用 NET MVC 4 所有服务都是使用 Ninject 注入的 我正在尝试使用 Quartz 来安排工作 目前 职位登记在Global asax如下 Global asax protected void Application S
  • MySQL 获取最高平均条目

    我正在尝试编写一个 mysql 查询来返回平均课程评分最高的前 3 门课程 我有两个表 评级和课程 评分表 courseId rating 1 6 2 2 1 4 2 5 3 3 4 0 6 0 课程表 courseId cnum cnam
  • Apple 登录无法在 iOS 14 模拟器上运行

    当我尝试登录 iOS 14 中的模拟器时 加载旋转器会一直旋转 Apple 开发者论坛上有一个主题here https developer apple com forums thread 651533但没有解决方案 苹果也没有回应 我当然可
  • 不确定我的自动编码器神经网络从 Keras 预测中给出的结果

    我正在尝试构建一个自动编码器神经网络 用于在单列文本列表中查找异常值 我的输入有 138 行 它们看起来像这样 amaze header 2 png amaze header png circle shape xml disableable
  • 如何从使用 exec() 的存储过程创建复杂类型?

    我想通过动态构造并执行的查询创建一个复杂类型 以便在实体管理器中使用exec 是否可以 既然我正在写一个过滤器 如果不可能的话你会做什么 另外 我正在使用 linq 进行评估 但过滤器需要许多表及其寄存器 因此效率是一个问题 谢谢 是的 您
  • 使用适用于 API v2 的 Dropbox Java SDK 时出现 SSLHandshakeException

    In a XPages我想使用的应用程序适用于 API v2 的 Dropbox Java SDK 2 1 2 获取有关我的 Dropbox 帐户的信息 以下代码用于检索相应的帐户对象 String atoken DbxRequestCon
  • Ruby 空白:{ :a => 1 } 比 {:a => 1} 更好吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 看看其他人的代码 在花括号块内包含额外的空格似乎很常见 这是有原因的吗 对我来说 这似乎增加了额外的击键 从而增加了丑陋 特别是当事情嵌套时 l
  • 通过 AJAX 加载的页面上的 reCAPTCHA 字段不会加载。建议?

    实例 没有 AJAX http utsarotaract org inc email php 使用 AJAX 单击给我们发送电子邮件链接 http utsarotaract org contact php 当我查看源页面时 一切正常 但是当
  • Selenium/BeautifulSoup - WebScrape 该字段

    我的代码运行良好 并打印除带有下拉列表的行之外的所有行的标题 例如 如果单击第 4 行 则会出现一个下拉菜单 我实现了一个 尝试 理论上会单击下拉菜单 然后拉出标题 但是 当我执行 click 并尝试打印时 对于具有这些下拉列表的行 它们不
  • Symfony 无法生成路由到样式表的 URL

    我在同一个文件夹中有两个 CSS 文件 具有相同的访问权限 在同一个 Twig 文件中进行测试时 一个 CSS 文件会生成该文件的 URL 并完美加载 而另一个会给出错误 Error 模板渲染期间抛出异常 无法为命名路由 assetic a
  • 使用 python 从 PC 麦克风获取音频输入

    我使用的是 ubuntu 16 04 我必须从我的电脑麦克风获取音频输入 我正在使用 python 3 我使用 pyalsaaudio 我从某处复制了代码 这是代码 import alsaaudio time audioop inp als
  • excel公式剥离html

    我想从文本值的左侧和右侧剥离所有 html 我有这个
  • 如何使用批处理文件同时运行多个python脚本

    我有很多 python 脚本 通过单击它们单独运行每个脚本是一件痛苦的事情 如何制作一个批处理文件来一次运行它们 只需制作一个像这样的脚本作为每个任务的后台 在 Windows 上 start B python script1 py sta
  • Android 的互补滤波器(陀螺仪 + 加速器)

    最近我做了一些研究 使用加速度计 陀螺仪来使用这些传感器来跟踪智能手机 而无需 GPS 的帮助 请参阅这篇文章 基于陀螺仪和加速度计的室内定位系统 https stackoverflow com questions 7499959 indo
  • 使用系统 python osx 进行 pip

    我使用 macports 安装了 python26 所以我的系统上正确的 python 是 opt local bin python 然而 当我这样做时 sudo pip install
  • 为什么我会看到“TypeError:字符串索引必须是整数”?

    我正在学习 Python 并试图将 GitHub 问题转化为可读的形式 使用以下建议如何将 JSON 转换为 CSV https stackoverflow com questions 1871524 convert from json t
  • 原始值与参考值

    我读过一本名为 Web 开发人员的专业 Javascript 的书 其中写道 变量由引用值或原始值分配 引用值是存储在内存中的对象 然后它没有提到原始值是如何存储的 所以我猜它没有存储在内存中 基于此 当我有这样的脚本时 var foo 1