首页 > web前端 > js教程 > JavaScript中可变分配和突变的指南

JavaScript中可变分配和突变的指南

尊渡假赌尊渡假赌尊渡假赌
发布: 2025-02-10 10:35:09
原创
529 人浏览过

JavaScript中可变分配和突变的指南

在JavaScript的世界中,您经常听到

突变,但是它们到底是什么,它们是邪恶的吗? 在本文中,我们将涵盖可变分配和突变的概念,并查看为什么 - 一起 - 它们对开发人员来说可能是一个真正的痛苦。我们将研究如何管理它们以避免问题,如何使用尽可能少的以及如何保持代码可预测。 如果您想更详细地探索此主题,或者与Modern JavaScript提高速度,请查看我的新书的第一章,学习免费使用JavaScript。 >

让我们从回到价值类型的基础知识开始吧……

>

钥匙要点

JavaScript值分类为原语(不变)和对象(可变),从而影响了可变分配和突变的行为。 使用“ const”不会阻止对象突变;它仅防止将变量重新分配到其他值或对象。>

'LET'关键字允许重新分配,使其适用于需要在整个代码中更改值的变量。

传播操作员(``…')对于创建对象的浅副本至关重要,从而避免了与复制划分的对象中的突变有关的问题。

突变本质上不是不好的,而应仔细管理以维持代码可预测性并最大程度地减少错误,尤其是在动态的Web应用程序中。

>

    >数据类型
  • JavaScript中的每个值都是原始值或对象。有七种不同的原始数据类型:
  • 数字,例如3、0,-4、0.625
  • >字符串,例如'Hello',“ world”,`hi`'''
  • booleans,true and false
  • null

未定义的

>符号 - 一个独特的令牌,保证永远不会与另一个符号冲突

    bigint-用于处理大整数值
  • 任何不是原始价值的东西都是一个对象,包括数组,日期,正则表达式,当然还有对象文字。功能是一种特殊的对象类型。它们绝对是对象,因为它们具有属性和方法,但也可以称为对象。
  • 变量分配
  • >变量分配是您在编码时学习的第一件事之一。例如,这是我们将数字3分配给变量熊的方式:>
  • 变量的常见隐喻是其中一个标签的框之一,其内部有值。上面的示例将被描绘成一个包含标签“熊”的盒子,其中3个值。
  • >考虑发生的事情的另一种思考方式是作为参考,将标签映射到3:
  • >的值

    JavaScript中可变分配和突变的指南

    如果我将数字3分配给另一个变量,则引用与熊相同的值:

    <span>const bears = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    JavaScript中可变分配和突变的指南

    变量熊和火枪手都引用相同的原始值3。我们可以使用严格的等价运算符对此进行验证,===:

    <span>let musketeers = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    如果两个变量都引用相同的值,则相等性操作员返回true。

    在使用对象时

    时有些陷入困境

    >先前的示例显示了要分配给变量的原始值。分配对象时使用相同的过程:

    此分配意味着变量Ghostbusters引用了一个对象:>
    bears <span>=== musketeers
    </span><span><< true
    </span>
    登录后复制
    登录后复制
    登录后复制

    但是,在将对象分配给变量时,一个很大的区别是,如果将另一个对象分配给另一个变量,它将引用一个完全不同的对象 - 即使两个对象文字看起来完全相同!例如,下面的作业看起来像变量TMNT(青少年突变体忍者神龟)引用与变量捉鬼敢死的对象:

    JavaScript中可变分配和突变的指南

    >即使变量Ghostbusters和Tmnt看起来像是引用相同对象,它们实际上都引用了一个完全不同的对象,我们可以看到我们是否使用严格的平等操作员检查

    <span>const ghostbusters = { number: 4 };
    </span>
    登录后复制
    登录后复制

    >变量重新分配
    <span>let tmnt = { number: 4 };
    </span>
    登录后复制
    登录后复制
    当在ES6中引入const关键字时,许多人错误地认为常数已被引入JavaScript,但事实并非如此。此关键字的名称有点误导。

    JavaScript中可变分配和突变的指南> const声明的任何变量均不能重新分配到另一个值。这适用于原始值和对象。例如,变量熊在上一节中使用const声明,因此它不能为其分配另一个值。如果我们尝试将数字2分配给变量熊,我们会发现一个错误:

    >

    对数字3的引用是固定的,熊变量无法重新分配另一个值。>

    >同样适用于对象。如果我们尝试将另一个对象分配给变量Ghostbusters,则会得到相同的错误:>

    使用LET

    >当关键字用于声明变量时,可以将其重新分配以稍后在我们的代码中引用不同的值。例如,我们使用LET声明了可变的火枪手,因此我们可以更改火枪手所引用的价值。如果D'Artagnan加入了火枪手,他们的人数将增加到4:
    ghostbusters <span>=== tmnt
    </span><span><< false
    </span>
    登录后复制
    登录后复制

    这可以做到这一点,因为让我们用来声明变量。我们可以根据我们喜欢的次数改变火态引用的价值。

    >

    也使用Let声明了变量TMNT,因此也可以重新分配以引用另一个对象(如果我们喜欢的话,或者完全是其他类型):>

    <span>const bears = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    请注意,变量TMNT现在引用a

    完全不同的对象;我们不仅将数字属性更改为5。 总而言之,如果您使用const声明一个变量,则无法重新分配其值,并且始终将引用最初分配给的相同原始值或对象。如果您使用LET声明一个变量,则可以根据程序后来要求将其值重新分配多次。

    >通常将尽可能多地视为良好实践,因为这意味着变量的价值保持恒定,并且代码更加一致和可预测,从而使其不容易出现错误和错误。 通过参考 在本机JavaScript中,您只能为变量分配值。即使看起来可以,您也无法分配变量来引用另一个变量。例如,stooges的数量与火枪手的数量相同,因此我们可以使用以下内容来分配变量stooges以引用与变量火枪手相同的值:

    这看起来像变量stooges正在引用变量步枪仪,如下图所示:

    但是,在本机JavaScript中,这是不可能的:变量只能引用实际值;它无法引用另一个变量。当您进行这样的作业时,实际发生的是,分配左侧的变量将引用右引用的变量的值,因此变量stooges将引用与Musketeers变量相同的值,这是数字3一旦完成了这项任务,Stooges变量根本没有连接到Stubketeers变量。

    <span>let musketeers = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    这意味着,如果D'Artagnan加入了火枪手,并且我们将火枪手的价值设置为4,则Stooges的价值将保持3.实际上,因为我们使用const声明了Stooges变量,所以我们无法设置它具有任何新价值;它将永远是3 总结:如果您使用const声明变量并将其设置为原始值,即使是通过对另一个变量的引用,则其值无法更改。这对您的代码有益,因为这意味着它将更加一致和可预测。

    JavaScript中可变分配和突变的指南突变

    如果可以更改值,则说一个值为

    >可变的

    。仅此而已:AJavaScript中可变分配和突变的指南突变

    是更改值的属性的行为。JavaScript中的所有原始价值均为

    不变的:您永远无法更改其属性。例如,如果我们将字符串“蛋糕”分配给可变食品,我们可以看到我们无法更改其任何属性:

    <span>const bears = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    如果我们试图将第一个字母更改为“ F”,看起来它已经改变了:>

    >但是,如果我们看一下变量的值,我们发现什么都没有改变:
    <span>let musketeers = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    >

    如果我们尝试更改长度属性,也会发生同样的事情:
    bears <span>=== musketeers
    </span><span><< true
    </span>
    登录后复制
    登录后复制
    登录后复制
    >

    >尽管返回值表示已更改了长度的属性,但快速检查表明它没有:
    <span>const ghostbusters = { number: 4 };
    </span>
    登录后复制
    登录后复制

    请注意,这与使用const而不是let声明变量无关。如果我们曾经使用过,我们可以将食物设置为引用另一根字符串,但我们无法更改其任何属性。不可能更改原始数据类型的任何属性,因为它们是不变的
    <span>let tmnt = { number: 4 };
    </span>
    登录后复制
    登录后复制
    。 JavaScript中的

    可变性和对象 相反,JavaScript中的所有对象都是可变的,这意味着即使使用const声明了它们的属性,也可以更改其属性(请记住,请记住并仅控制一个变量是否可以重新签名,并且与可变性)。例如,我们可以使用以下代码更改数组的第一项:>

    请注意,尽管我们使用const宣布了可变食品,但仍会发生这种变化。这表明使用const

    不会阻止对象被突变

    >我们也可以更改数组的长度属性,即使已使用const声明了数组:>
    ghostbusters <span>=== tmnt
    </span><span><< false
    </span>
    登录后复制
    登录后复制

    >通过参考复制 >请记住,当我们将变量分配给对象文字时,变量也将完全不同的对象引用,即使它们看起来相同:

    >

    bears <span>= 2;
    </span><span><< TypeError: Attempted to assign to readonly property.
    </span>
    登录后复制

    但是,如果我们将变量factant4分配给另一个变量,它们都会引用相同

    对象:>

    ghostbusters <span>= {number: 5};
    </span><span>TypeError: Attempted to assign to readonly property.
    </span>
    登录后复制
    这将变量factany4分配给引用

    与变量TMNT引用的对象相同,而不是完全不同的对象。 JavaScript中可变分配和突变的指南

    这通常称为通过引用复制,因为两个变量都分配给引用

    > same
    musketeers <span>= 4;
    </span>
    登录后复制
    对象。

    这很重要,因为对此对象进行的任何突变都将在两个变量中都可以看到。 >因此,如果蜘蛛侠加入神奇四侠,我们可能会更新对象中的数字值:>

    这是一个突变,因为我们已经更改了数字属性,而不是设置factand4来引用新对象。JavaScript中可变分配和突变的指南

    这会导致我们一个问题,因为TMNT的数量属性也会改变,甚至可能没有我们意识到:>
    <span>const bears = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    这是因为TMNT和FANTANDY4都在引用相同的对象,因此任何对TMNT或FANTANDEN的突变都会影响它们两个。

    >这突出了JavaScript中的一个重要概念:当对象通过参考复制并随后突变时,突变会影响任何引用该对象的任何其他变量。这可能会导致意外的副作用和难以追踪的错误。

    抢救的传播操作员!

    >

    >那么,如何在不创建对原始对象的引用的情况下制作对象的副本?答案是使用传播操作员!

    >传播操作员是在ES2015中的阵列和字符串以及ES2018中的对象引入的。它使您可以轻松地制作对象的浅副本,而无需创建对原始对象的引用。

    >下面的示例显示了我们如何设置可变factany4来引用tmnt对象的副本。该副本将与TMNT对象完全相同,但是fancally4将引用一个全新的对象。这是通过将要复制的变量的名称放置在对象中的文字中,并在其前面的传播操作员来完成:>

    >我们在这里实际完成的是将变量factally4分配给新对象文字,然后使用传播操作员复制TMNT变量引用的对象的所有枚举属性。由于这些属性是值,因此它们按值将其复制到奇妙的4个对象中,而不是通过参考。
    <span>let musketeers = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    >

    JavaScript中可变分配和突变的指南>现在,对任何一个对象进行的任何更改都不会影响另一个对象。例如,如果我们将fandand4变量的数字属性更新为5,则不会影响tmnt变量:

    >

    bears <span>=== musketeers
    </span><span><< true
    </span>
    登录后复制
    登录后复制
    登录后复制

    JavaScript中可变分配和突变的指南>传播运算符还具有有用的快捷方式表示法,可用于制作对象的副本,然后在单个代码行中对新对象进行一些更改。> 例如,说我们想创建一个对象来建模青少年忍者神龟。我们可以创建第一个乌龟对象,并为其分配可变的leonardo:>

    除武器和颜色特性外,其他乌龟都具有相同的特性,每只乌龟都不同。使用ever operator,然后更改武器和颜色属性,将列昂纳多引用的对象复制进行副本,就像:

    一样:

    >我们可以通过添加引用在vread对象后要更改的属性来在一行中执行此操作。这是为变量Donatello和Raphael创建新对象的代码:

    <span>const bears = 3;
    </span>
    登录后复制
    登录后复制
    登录后复制
    登录后复制
    登录后复制

    >请注意,以这种方式使用传播操作员只能使对象的浅副本。要进行深层副本,您必须递归进行此操作或使用库。就个人而言,我建议您尝试使物体尽可能浅。

    突变不好?

    在本文中,我们介绍了可变分配和突变的概念,并看到了为什么 - 它们对开发人员来说可能是一个真正的痛苦。

    突变的声誉不好,但它们本身并不一定是不好的。实际上,如果您要构建动态的Web应用程序,则必须在某个时候改变。从字面上看,这就是“动态”一词的含义!这意味着您的代码中必须存在一些突变。话虽如此,突变越少,您的代码就会越容易预测,使维护更容易,并且不太可能开发任何错误。

    一种特别有毒的组合正在通过参考和突变复制。这可能会导致您甚至没有意识到发生的副作用和错误。如果您突变代码中另一个变量引用的对象,则可能会导致许多可能难以追踪的问题。关键是尝试最大程度地减少您对突变的使用,并跟踪哪些物体已被突变。 在功能编程中,纯函数是不会引起任何副作用的功能,突变是副作用的最大原因之一。

    黄金法则是避免通过参考复制任何对象。如果要复制另一个对象,请使用传播操作员,然后在制作副本后立即进行任何突变。

    接下来,我们将研究JavaScript中的数组突变。

    如果您想通过现代JavaScript加快速度,请不要忘记查看我的新书与JavaScript学习代码。您可以免费阅读第一章。如果您有任何疑问或评论,请在Twitter上与您联系!

    经常询问有关JavaScript变量分配和突变的问题(常见问题解答)

    > JavaScript中的变量分配与突变之间有什么区别?例如,令x = 5;在这里,我们将值5分配给变量x。另一方面,突变是指更改现有变量价值的过程。例如,如果我们以后写x = 10;我们通过将其值从5更改为10来突变x。

    > JavaScript在原始和非基本数据类型中如何处理可变分配和突变?

    > JavaScript处理原始数据类型(例如数字,字符串和布尔值)和非主要数据类型(例如对象(例如对象)在变量分配和突变方面,阵列的不同。对于原始数据类型,当您分配变量时,将创建并存储在新的内存位置中。但是,对于非主要数据类型,当您分配变量时,两个变量都指向同一内存位置。因此,如果您突变一个变量,则将变化反映在所有指向该内存位置的变量中。

    >

    >在JavaScript中,逐个传递和逐次参考的概念是什么?

    >通过逐步传递和通过引用是JavaScript可以将变量传递到函数的两种方式。当JavaScript通过值通过变量时,它会创建变量值的副本,并将复制到函数的副本。对函数内部变量的任何更改都不会影响原始变量。但是,当JavaScript通过引用传递变量时,它将引用对变量的内存位置。因此,对函数内部变量的任何更改也会影响原始变量。

    >如何防止JavaScript中的突变?

    >有几种方法可以防止JavaScript突变。一种方法是使用object.freeze()方法,该方法可防止新属性被添加到对象,现有属性被删除,并防止更改现有属性的枚举性,可配置性或书写性。另一种方法是在声明变量时使用const关键字。这样可以防止重新分配变量,但是如果该值是对象或数组。 🎜>在JavaScript中,对象的浅副本是对象的副本,其中原始对象的值和副本指向非原始数据类型的同一内存位置。因此,如果将副本变异,则原始对象也会突变。另一方面,对象的深副本是对象的副本,其中原始对象和副本的值未指向相同的内存位置。因此,如果将副本变异,则原始对象不会被突变。

    >

    >如何在JavaScript中创建对象的深副本?在JavaScript中是使用JSON.PARSE()和JSON.STRINGIFY()方法。 JSON.STRINGIFY()方法将对象转换为JSON字符串,而JSON.PARSE()方法将JSON字符串转换回对象。这将创建一个新对象,它是原始对象的深副本。

    >

    > JavaScript中的突变处理器API是什么?它旨在提供一般,高效且健壮的API,以对文档中的更改做出反应。

    > JavaScript如何在封闭情况下如何处理变量分配和突变?闭合是一个函数,它具有访问其自己的范围,外部函数范围和全局范围的函数。当变量被分配或在闭合内部突变时,它可能会影响外部范围中变量的值,具体取决于该变量是在闭合范围中声明还是外部范围。在JavaScript?

    中的var,let和const之间,在JavaScript,var,let和const中用于声明变量。 VAR是函数范围的,如果在函数之外声明它,则将其在全球范围内进行范围。让我们的const是块范围的,这意味着它们仅存在于其声明的块中。let and const之间的差异是让允许重新分配,而const却不。在JavaScript中异步编程的上下文中,异步编程允许同时进行多个事物。当变量在异步函数中分配或突变时,如果代码的其他部分依赖于变量的值,则会导致意外结果。这是因为在代码的其他部分运行之前,变量分配或突变可能尚未完成。为了解决此问题,JavaScript提供了多个功能,例如Promises和Async/等待,以帮助管理异步代码。

    >

以上是JavaScript中可变分配和突变的指南的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板