通过引用传递和拼接

时间:2017-04-26 12:14:30

标签: javascript arrays object

我试图更好地理解引用传递如何与splice相关。我想拥有一个主要的对象数组,并使用另一个引用主数组对象的数组。例如:

var mainArray = [
    someObject,
    anotherObject
]
var subArray = [];
subArray.push( mainArray[ 0 ] );

我不明白如果我拼接原始值会发生什么?

mainArray.splice( 0, 1 );

subArray [0]:

  1. 也会被拼接?
  2. 由于存在指向它的指针,该值是否仍然存在?
  3. 留空值?

3 个答案:

答案 0 :(得分:4)

在此代码之后:

var mainArray = [
    someObject,
    anotherObject
];
var subArray = [];
subArray.push( mainArray[ 0 ] );

...你在记忆中看到的东西看起来有点像这样:

                                                   +−−−−−−−−−−+
someObject−−−−−−−−−−−−−−−−−−+−−+−−−−−−−−−−−−−−−−−−>| (object) |
                           /  /                    +−−−−−−−−−−+
                           |  |    
                           |  |                     +−−−−−−−−−−+
                           |  |  anotherObject−−−+−>| (object) |
                           |  |                 /   +−−−−−−−−−−+
                           |  |                |
             +−−−−−−−−−−−+ |  |                |
subArray−−−−>| (array)   | |  |                |
             +−−−−−−−−−−−+ |  |                |
             | length: 1 | |  |                |
             | 0:        |−/  |                |
             +−−−−−−−−−−−+    |                |
                              |                |
              +−−−−−−−−−−−+   |                |
mainArray−−−−>| (array)   |   |                |
              +−−−−−−−−−−−+   |                |
              | length: 2 |   |                |
              | 0:        |−−/                 |
              | 1:        |−−−−−−−−−−−−−−−−−−−−/
              +−−−−−−−−−−−+

请注意,mainArraysubArray之间根本没有联系。它们恰好都包含相同的值(也是someObject中的值,所有三个地方都有同一对象的对象引用)。​​

mainArray中删除该值对subArray(或对象)没有影响:

mainArray.splice(0, 1);
                                                   +−−−−−−−−−−+
someObject−−−−−−−−−−−−−−−−−−+−−−−−−−−−−−−−−−−−−−−−>| (object) |
                           /                       +−−−−−−−−−−+
                           |       
                           |                        +−−−−−−−−−−+
                           |     anotherObject−−−+−>| (object) |
                           |                    /   +−−−−−−−−−−+
                           |                   |
             +−−−−−−−−−−−+ |                   |
subArray−−−−>|  (array)  | |                   |
             +−−−−−−−−−−−+ |                   |
             | length: 1 | |                   |
             | 0:        |−/                   |
             +−−−−−−−−−−−+                     |
                                               |
              +−−−−−−−−−−−+                    |
mainArray−−−−>|  (array)  |                    |
              +−−−−−−−−−−−+                    |
              | length: 1 |                    |
              | 0:        |−−−−−−−−−−−−−−−−−−−−/
              +−−−−−−−−−−−+

基于此:

  

1。也会被拼接?

不,更改mainArary的内容对subArray没有影响。

  

2。该值仍然存在,因为有一个指向它的指针?

subArray条目0的值不受影响。

  

3。留下空值?

不,对subArray完全没有影响。

  

我正在努力更好地理解引用传递如何与splice相关。

你在那里混淆了“引用”一词的两个不同含义(很多人都这样做)。

“传递参考”是编程中的术语。也就是说,它具有特定含义:将对变量的引用传递给函数,以便函数可以伸出并更改该变量的内容。 JavaScript没有传递引用。

你在问题​​中处理的是对象引用,它与传递引用无关,只是两个概念都包含“引用”这个词(但是在关系中)完全不同的东西。)

对象引用是值。它们告诉JavaScript引擎对象在内存中的位置。

答案 1 :(得分:1)

有趣的是,这与最近的另一个问题非常相似,尽管不是一个愚蠢的问题。

设置一个试图在谨慎组件中使用此类引用的数据结构是一条黑暗的道路。有趣的是,如果你只是在使用一些代码,但在部署的应用程序中,这是一个麻烦。

最好创建一个结构,通过创建更改的组件将模型的更改写入该模型,然后模型广播“脏数据”事件(或任何您想要调用的事件),其中包含新数据,已注册的侦听器(例如其他组件)正在侦听。他们接收数据有效负载并使用它。

对于需要按需数据的组件,您可以注入服务/访问单例/您的框架所做的任何事情,并通过getter或某种简单的工厂函数访问它。

以你正在做的方式改变对象越来越不受欢迎。传递相关对象的不可变(或至少复制)版本更好。这样,如果该对象发生变化,则很容易找出原因和原因。如果一切都有一个实际有用的参考(正如你在上面看到的那样,通常没有),对它们中的任何一个进行小的改动都会破坏你的早晨。

如果您想知道,复制对象并不难。您可以简单地以这种方式复制对象(假设它包含基本对象,基本类型等)

let myNewObj = Object.assign ( {}, myOldObj );
let myNewArr = [].concat ( myOldArr );

如果该对象包含带有对象等的数组,则可以使用这个老技巧进行深度复制:

let myFancyObjJSON = JSON.stringify ( myFancyObj )
let copy = JSON.parse ( myFancyObjJSON )

绝大部分时间都可以使用,除非您的类型不典型(例如,带有符号键的地图忽略了这些键)以及其他一些不常遇到的日常情况。

相信我,根据经验,重新思考你的结构(再次,除非这只是一个实验)。

答案 2 :(得分:0)

我已经扩展了你的例子以试图澄清正在发生的事情

var mainArray = [
    {a: 1},
    {b: 2}
]
var subArray = [];
subArray.push( mainArray[ 0 ] );

mainArray.splice( 1, 1 );  // remove b from mainArray

subArray[0].a = 5 // set a in subArray to 5

console.log(mainArray, subArray); // [{a:5}] [{a:5}] a = 5 in both array ( same object )

var third = subArray;

third[0].a = 15;

console.log(mainArray, subArray, third); // [{a:15}] [{a:15}] [{a:15}] 
                                         // the same object a is changed everywhere

third.splice(0, 1);

console.log(mainArray, subArray, third); // [{a:15}] [] []
                                         // mainArray ---> object x ---> x[0] ---> a
                                         // third and subArray ---> object y ---> y[0] ---> a
                                         // there's no link between x and y directly