【问题标题】:How to pass Javascript properties correctly such that they can be modified by a function如何正确传递 Javascript 属性,以便它们可以被函数修改
【发布时间】:2021-11-23 09:37:23
【问题描述】:

我知道 JavaScript 对象,包括数组,是通过引用自动传递的,所以我有这样的东西:

class Thing {
    constructor( ) {
        this.letters = [ "A", "B" ];
        this.numbers = [ 1, 2, 3 ];

        this.change( this.letters, this.numbers );
    }

    change( _letters, _numbers ) {
        let l = _letters;
        let n = _numbers;

        l = [ ];
        n = 6;
    }
}

var t = new Thing( );
console.log( t );

日志请求显示Thing的属性没有变化。然而,在我无法识别的不同情况下,我不小心修改了函数内部传递的参数,不得不使用n = Array.from( _numbers ) 之类的东西来避免修改源属性。 谁能解释发生了什么,为什么?

我想通过引用传递对象属性,这样我就可以在单个函数调用中修改多个相关属性,从而保留返回值用于调试目的。

谢谢。

【问题讨论】:

  • 您的示例没有修改对象,您只是重新分配变量。您必须访问某些属性才能修改对象,例如 _letters[1] = 'C' 或 l[1] = 'C'
  • 对于@PatrickEvans,在change()、l 和n 的前两行是对您类的属性的引用。但是,在接下来的两行中,您将这些变量重新分配为现在对空数组的引用,并且 6.l 和 n 不再引用您的类的属性,它们现在引用在 change() 范围内声明的值。
  • @DylanLandry:谢谢。这是完全有道理的。那么,我们通常(或在最佳实践中)如何修改传递的对象?是否只有通过引用(例如 _letters[1] )和迭代才能改变原始值?
  • @DylanLandry 好吧,不,l 和 n 不是参考。它们所做的只是分别保持与this.letters 和this.numbers 属性相同的对象引用。
  • @POD JavaScript 中没有传递引用。虽然有参考值的传递。

标签: javascript parameter-passing javascript-objects pass-by-reference


【解决方案1】:

问题在于范围。当您使用 let 声明时,声明的范围为函数 change,并且您还在这里重新分配了块范围的变量:

l = [ ];
n = 6;

如果你想改变类属性,你可以这样做:

change(_letters, _numbers) {
    this.letters = _letters; // `this` scoped to class
    this.numbers = _numbers; // `this` scoped to class
  }

看例子:

// simple demo start
let numbers = [1, 2, 3];

let n = numbers;
n.push(4)
console.info(n, typeof n);

n = 6; // reassign n
console.info(n, typeof n, numbers);
// simple demo end

// refactored class
class Thing {
  constructor() {
    this.letters = ["A", "B"];
    this.numbers = [1, 2, 3];

    this.change(this.letters, this.numbers);
  }

  change(_letters, _numbers) {
    let l = _letters; // `let` is scoped to `change()`
    let n = _numbers; // `let` is scoped to `change()`

    l = []; // only changes scoped l
    n = 6; // only changes scoped n
  }

  changeFix(_letters, _numbers) {
    this.letters = _letters; // `this` scoped to class
    this.numbers = _numbers; // `this` scoped to class
  }
}

var t = new Thing();
console.log(t);

t.change(['C'], [4]);
console.info(t);

t.changeFix(['C'], [4]);
console.info(t);

【讨论】:

  • 也可以通过类实例从类外部编辑类属性:i.numbers = [4,5,6];
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
  • 2018-07-12
  • 1970-01-01
相关资源
最近更新 更多