Javascript:为什么在某些情况下对象的值会发生变化,而其他情况下将其传递给函数后不会发生变化?

标签 javascript immutability mutability

我这里有四个案例,执行结果如注释中所示。我真正不明白的是,在某些情况下,值可以改变,但有些则不能。有谁能提供一个答案,即不变性和可变性如何在 javascript 中为变量赋值?我认为这可能是一个典型的面试问题...但我无法清楚地解释它是如何运作的...

案例1

const x = { a: 1, b: 2 };
function fn1(_x) {
    _x.a = 0;
}
fn1(x);
console.log(x);
// { a: 0, b: 2 }          mutated

案例2

const y = { a: 1, b: 2 };
function fn2(_y) {
    _y = 0;
}
fn2(y.a);
console.log(y);
// { a: 1, b: 2 }          not mutated

我从这个示例代码中得到的是,如果没有在函数中显式赋值,则对象属性的值无法更改。

<小时/>

案例3

const z1 = { a: 1, b: 2 };
function fn3({ a }) {
    a = 0;
    a.c = 0;
}
fn3(z1);
console.log(z1);
// { a: 1, b: 2 }          not mutated

案例4

const z2 = { a: {}, b: 2 };
function fn3({ a }) {
    a = 0;
    a.c = 0;
}
fn3(z2);
console.log(z2);
// { a: {}, b: 2 }         not mutated

在情况 4 中我期望的是 //{ a: {}, b: 2 }。为什么 z2 的值发生了变化,而 z1 的值却没有变化?这是因为 StringNumber 是不可变的?

<小时/>

根据这些实验,我是否可以假设只有当我将其显式分配给函数中对象的属性时,该值才会更改?我还将假设 Array 的行为与 Object 中的行为相同。

谢谢!

<小时/>

更新:

案例5

const z2 = { a: {}, b: 2 };
function fn4({ a }) {
    a.c = 0;
    a = 0;
}
fn3(z2);
console.log(z2);
// { a: { c: 0 }, b: 2 }        mutated

帕特里克·罗伯茨刚刚指出“先前的”情况 4 是不可变的,我之前没有注意到这一点......但令我感兴趣的是,通过翻转 a.c = 0;< 的顺序a = 0;,即案例 5 中的 fn4,输出发生变化...但这就是我存放的位置...对于之前的错误感到抱歉案例 4 中的输出。

最佳答案

情况 1 中,您将传递对对象的引用并更改其属性之一,而在情况 2 中,您将向函数传递一个值,并改变其属性之一。用它做某事。 _yfn2(_y) 范围内的变量,它不存在于其外部,调用 fn2(y.a) 是与调用 fn2(1) 相同,因此,它不会改变 y 上的任何内容。

情况3情况4都使用新的对象解构语法,这些代码是等效的:

function fn3({ a }) {
    a = 0;
    a.c = 0;
}

function fn3(x) {
    var a = x.a;
    a = 0;
    a.c = 0;
}

因此,在情况 3 中调用 fn3 是按值传递,就像情况 2 一样。

情况 4 不会改变对象。

更新 案例5

const z2 = { a: {}, b: 2 };
function fn4({ a }) {
    a.c = 0;
    a = 0;
}
fn4(z2);
console.log(z2);

在案例 5 中,您是吊装的“受害者”。。该代码不会按照编写的顺序执行。在 JS 中声明任何变量都相当于在封闭范围的顶部声明它。该作用域将是 var 的封闭函数以及 letconst 的大括号。前面的代码相当于:

const z2 = { a: {}, b: 2 };
function fn4(x) {
   var a = 0;
   x.a.c = 0;
}
fn4(z2);
console.log(z2);

原因是,当您声明 a = 0 时,它会被提升到函数的顶部,并且从参数中获取的 a 是不同的 a,即传递给函数的对象中对 a 属性的引用。

关于Javascript:为什么在某些情况下对象的值会发生变化,而其他情况下将其传递给函数后不会发生变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48532636/

相关文章:

javascript - 放大图像 (JavaScript)

javascript - 标签上的 Jquery textextjs twitter bootstrap 无法正常工作

java - 如何实现使用模板的界面?

javascript - 更新对象数组中的属性

Python:更新引用值

C99:记录线程安全的受限指针?

javascript - 如果在另一个数组中找到值,则不会始终从数组中删除该值

javascript - 如果目标元素被删除,带有 "body"容器集的 Bootstrap 弹出窗口不会删除弹出窗口

java - 不可变对象(immutable对象)的 null 和默认行为

rust - 与内部可变性作斗争