数组的奇数javascript变量行为

数组的奇数javascript变量行为,javascript,arrays,variables,Javascript,Arrays,Variables,希望这个问题以前没有被问过。无论如何,我找不到它。 我已经注意到这种似乎只发生在数组中的变量行为 var arr = [], arr2 = arr; alert(arr2); // empty arr.push(1); alert(arr2); // 1 下面是我通常期望变量的行为 var k = 10, m = k; alert(m); //10 k+=1; alert(m); //10 现在看看它们在数组中的行为 var arr = [], arr2 = arr;

希望这个问题以前没有被问过。无论如何,我找不到它。 我已经注意到这种似乎只发生在数组中的变量行为

var arr = [],
    arr2 = arr;
alert(arr2); // empty
arr.push(1);
alert(arr2); // 1
下面是我通常期望变量的行为

var k = 10,
    m = k;
alert(m); //10
k+=1;
alert(m); //10
现在看看它们在数组中的行为

var arr = [],
    arr2 = arr;
alert(arr2); // empty
arr.push(1);
alert(arr2); // 1
对于数组,变量似乎只是对同一数组的引用,对于数字,它们表示具有相同值的两个不同数字


如果这是一个noob问题,我很抱歉,但我刚刚注意到了。所有复杂类型都是这样吗?我想知道这种行为背后的原因。语言通过这样做实现了什么?

两个数组对象都指向相同的变量。这就是为什么一个会改变另一个会受到影响的原因。数字在javascript中是原语。这意味着实际数据直接存储在变量本身上

var k = 10,
    m = k;
在第一种情况下,
m
k
接收10的两个不同副本。赋值操作复制值,m上的任何更改不会影响其他副本,反之亦然(因为它们是两个不同的副本)

相反,数组是javascript中的引用类型

var arr = [],
    arr2 = arr;

赋值操作复制地址,因此通过一个变量对对象进行的任何修改都会影响另一个变量。

在第一个代码块中,首先从

+-------+ +--------------+ | k: 10 | | m: undefined | +-------+ +--------------+ 将
k
中的值复制到
m

+-------+ +-------+ | k: 10 | | m: 10 | +-------+ +-------+ +-------+ +-------+ | k: 11 | | m: 10 | +-------+ +-------+ 在第二个代码块中,从以下内容开始:

+------+ | arr |------+ +------+ | +-----------+ +-->| (array ) | +------+ | +-----------+ | arr2 |------+ | length: 0 | +------+ +-----------+ 所有复杂类型都是这样吗

是的,这适用于所有对象(标准数组只是JavaScript中的对象),以及新类型的数组

要记住的关键是变量包含值。当变量引用对象或数组时,变量中的值是对对象/数组的引用,而不是其副本


让人们牢牢记住对象引用是与数字一样的值,这对理解JavaScript代码(以及其他几种在这方面工作方式相同的语言,如Java)非常有益。

我想我也可以回答为什么会发生这种情况:

javascript中有两种类型的值:

  • 复杂类型
  • 基本类型
  • 复杂类型通常被称为对象:

    []
    {}
    new String()
    new Date()
    
    现在,基本类型包括:

    'a string'
    23
    true
    
    所以这里的答案是引用在复杂类型和基本类型上的行为不同

    var aString = 'myString';
    var refString = aString;
    
    在本例中,“aString”的值被复制到refString。它们是两个完全独立的价值观。但引用复杂类型:

    var anArray = [];
    var refArray = anArray;
    
    var anObject = {};
    var refObject = anObject;
    
    在本例中,两个变量中的数组完全相同,对象也是如此

    这也转移到检查平等性:

    'my string' === 'my string' // true
    23 === 23 // true
    true === true // true
    
    Javascript实际上只是看到这些值彼此相似,而不是内存中的值完全相同。查看复杂类型:

    {} === {} // false
    [] === [] // false
    
    var myObject = {};
    var myObjectReferenced = myObject;
    myObject === myObjectReferenced // true
    
    这是理解JavaScript的一个非常重要的核心概念,否则您将面临更改您认为独特但实际上共享的对象的高风险


    希望这是一个好的解释。

    JavaScript中有两种变量(以及其他语言中的变量)。第一种是为所谓的“原始”类型保留的,主要是数字、字符串和布尔值。第二种类型是“参考”类型,即所有其他类型的对象

    您可以这样考虑:对于基本类型,每个值都存储在自己的抽屉中。例如,抽屉x的值为1,抽屉y的值为“John”,等等。因此,当您访问抽屉x时,您直接访问里面的值

    对于引用类型,您只存储如何从隐藏在后面某个位置的自身内存位置检索该值的方向,而不是将变量的值存储在抽屉中。因此,当您将“引用抽屉”的内容复制到另一个变量时,您并没有复制值,而只是复制方向,因此现在您有两个抽屉,它们具有访问相同值的方向


    这样做的原因相当复杂,但基本上与尽可能高效地管理程序的内存有关。

    复制复杂的数据结构在CPU和内存方面非常昂贵,通常不需要。阿尔瓦罗G.维卡里奥感谢您现在就得到了arr2=arr.slice(0);将创建一个副本而不是引用是的,谢谢,相等部分也很重要,实际上我今天在递归置换函数中为此损失了很多时间,该函数本不应该共享一些数组,但一直共享它们,但现在它工作了。是的,这是正式的最佳答案。
    {} === {} // false
    [] === [] // false
    
    var myObject = {};
    var myObjectReferenced = myObject;
    myObject === myObjectReferenced // true