Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Array.push()和Spread语法之间的差异_Javascript_Arrays_Algorithm_Ecmascript 6_Dynamic Programming - Fatal编程技术网

Javascript Array.push()和Spread语法之间的差异

Javascript Array.push()和Spread语法之间的差异,javascript,arrays,algorithm,ecmascript-6,dynamic-programming,Javascript,Arrays,Algorithm,Ecmascript 6,Dynamic Programming,算法问题陈述:找到与目标和相加的最小数组 代码问题: 我不理解以下情况下的结果差异: 使用arr.push()方法 vs 使用扩展语法 请参考下面的评论行 Spread语法返回正确的解决方案,而.push()方法继续推送到同一数组上。我不明白为什么它总是引用内存中的相同数组 非常感谢 let howSum = (target, arr, memo = {}) => { if (target in memo) return memo[target]; if (targ

算法问题陈述:找到与目标和相加的最小数组

代码问题: 我不理解以下情况下的结果差异:

  • 使用arr.push()方法
vs

  • 使用扩展语法
请参考下面的评论行

Spread语法返回正确的解决方案,而.push()方法继续推送到同一数组上。我不明白为什么它总是引用内存中的相同数组

非常感谢

let howSum = (target, arr, memo = {}) => {
    if (target in memo) return memo[target];
    if (target === 0) return [];
    if (target < 0) return null;

    let smallest = null;

    for (let e of arr) {
        if (howSum(target - e, arr, memo) !== null) {
            let result = howSum(target - e, arr, memo);
            // result.push(e);
            result = [...result, e];

            if (smallest === null || result.length < smallest.length) {
                smallest = result;
            }
        }
    }

    memo[target] = smallest;
    return smallest;
};

console.log(howSum(10, [1, 2, 5])); // [5, 5]
let howSum=(target,arr,memo={})=>{
如果(备忘录中的目标)返回备忘录[目标];
如果(目标===0)返回[];
if(target<0)返回null;
设最小值=null;
对于(让e代表arr){
if(howSum(目标-e、arr、memo)!=null){
让结果=howSum(目标-e、arr、备忘录);
//结果:推(e);
结果=[…结果,e];
if(最小===null | | result.length<最小.length){
最小=结果;
}
}
}
备注[目标]=最小值;
返回最小;
};
log(howSum(10[1,2,5]);//[5, 5]
array.push(元素)
vs.
array=[…array,element]
Array.push
将一个元素添加到现有数组的末尾,同时扩展语法创建一个全新的数组。例如,以下代码将抛出错误,因为我们正在尝试重新定义
常量

const array = ["foo", "bar"];
array = [...array, "baz"]; // Uncaught TypeError: invalid assignment to const 'array'
Array.push将添加到现有数组中,因此无需重新定义:

const array = ["foo", "bar"];
array.push("baz"); // No error; "baz" is successfully added to the end of the array.
另一个区别是速度
array.push(元素)
array=[…数组,元素]


同样,扩展语法本身并不创建新数组。您也可以在这样的函数中使用扩展语法:
myFunction(…myArray)
。这将使用数组元素作为参数。所以换句话说,
..myArray
不会创建新的数组,但是
[…myArray]
会创建新的数组。只是一个值得注意的小细节


为什么循环在内存中不断引用同一数组 Spread语法返回正确的解决方案,而.push()方法继续推送到同一数组上。我不明白为什么它总是引用内存中的相同数组

JavaScript中的对象(JavaScript数组是对象)是引用类型而不是值类型。因此,使用排列语法,您可以创建一个新数组(
result
),但仍然为函数提供旧数组(
arr
)。使用
Array.push
时,可以修改提供给函数的数组。由于您修改了所提供的数组(而不是创建本地数组),因此将继续使用数组中的新值调用函数。使用排列语法时,创建一个新数组(因此
result
不引用
arr
数组),当使用
arr
参数调用函数时,仍然具有与第一次调用函数时相同的值

@trincot写了你的代码中发生了什么

下面是一个可以在JavaScript控制台中进行的实验:

const myArray = ["foo", "bar"];

function changeArray(arrayParameter) {
  const arrayVariable = arrayParameter;
  // We are still referencing the array that was supplied to our function, so
  // although it looks like we tried to duplicate the array, arrayVariable.push,
  // arrayParameter.push, and myArray.push will all modify the same array.
  arrayVariable.push("baz");
}

changeArray();
console.log(myArray); // ["foo", "bar", "baz"]
.push()
方法继续推送到同一个数组上。我不明白为什么它总是引用内存中的相同数组

如果我们采用您的代码变体,其中您不使用扩展语法,而是
push
,那么请意识到:

  • push
    对数组进行变异,但不会创建新的数组
  • 代码创建新数组的唯一位置是
    return[]
那么,看看在返回[]
之后会发生什么:

  • result.push(e)
    会将该数组更改为
    [e]
  • 第一次
    最小值
    为空,因此
    最小值
    成为对单个数组的引用
  • memo[target]
  • 此引用返回给调用者,调用者将其分配给
    result
  • 将一个新值推送到该单个数组,该数组现在有两个元素。现在它来了:
  • 由于上面提到的
    memo[target]
    引用了与
    result
    相同的数组,您实际上已经对
    memo[target]
    进行了变异:
    memo[target]。长度现在将为2

这是不希望的。一旦您将数组分配给
memo
,它就永远不会发生变化。这就是为什么在代码中的某个时刻,您应该创建一个新数组的原因。

result=[…result,e]创建一个新数组。这并不是因为专门使用了spread,这只是因为
result=[]
result
分配了一个新数组。好吧,“我不明白为什么它在内存中一直引用同一个数组”的答案是它是经过设计的。如果使用得当,在改变对象而不是创建新对象方面会有很多用处。@FelixKling,谢谢。你能再详细一点吗?最后一步是通过添加新元素来更新数组。这两种方法不是都可以完成更新旧阵列吗?我可以更新相同的数组,也可以使用更新后的值创建一个新数组。我想如果不创建新数组,那么每个
memo[target]
条目都引用一个相同的数组,这意味着每个
target
的已记忆解决方案完全相同,这在概念上显然是错误的。小更正:Spread语法不会创建数组。数组文本创建数组。当然,扩展元素只能在数组文本中使用。感谢@Samuel Ebert,但是数组不是for循环中的块范围变量吗?这样在下一次迭代中就被从记忆中抹去了吗?@SamuelEbert谢谢,所以这又回到了我困惑的根源。如果“结果”数组在