为什么第一个console.log()打印未定义的值,但第二个已转换值

时间:2017-08-05 03:18:40

标签: javascript

为什么第一个console.log()会打印未定义的值,但第二个已经转换了值?我知道它必须对功能范围做一些事情,但没有得到它

var array = [1,2,3,4,5,7];


function incrementByOne(arr) {
  arr = arr.map(function(value, index, array){
    arr[index] = arr[index] +1;
  
  
  });
  console.log(arr);
}



incrementByOne(array);

console.log(array);

// [undefined, undefined, undefined, undefined, undefined, undefined]

// [2, 3, 4, 5, 6, 8]

我还注意到第一个console.log()知道迭代次数但是值会发生什么......

js bin link

4 个答案:

答案 0 :(得分:2)

您需要从map中的函数返回递增的值。使用return arr[index] +1 您还需要返回使用map形成的新数组并存储在arr中。

var array = [1,2,3,4,5,7];


function incrementByOne(arr) { //contains array reference
  arr = arr.map(function(value, index, array){
    return value +1;
  });
  //now arr contains a new array and doesn't refer to passed array anymore.
  console.log(arr);
  return arr;
}


array = incrementByOne(array);

console.log(array);

// [undefined, undefined, undefined, undefined, undefined, undefined]

// [2, 3, 4, 5, 6, 8]

如果你不想返回,你可以使用forEach(),因为在这种情况下,arr将引用传递的数组。不同之处在于map返回一个新数组。

var array = [1,2,3,4,5,7];


function incrementByOne(arr) { //contains array reference
  arr.forEach(function(value, index){
    arr[index] = value +1;
  });
  //arr still refers to the passed array.
  console.log(arr);
}


incrementByOne(array);

console.log(array);

// [undefined, undefined, undefined, undefined, undefined, undefined]

// [2, 3, 4, 5, 6, 8]

答案 1 :(得分:0)

这里发生了一些事情:

  1. 传递给.map函数的回调应返回带有return关键字的值。如果您没有从回调中返回值,则默认返回值是未定义的。这就是为什么' arr'您在incrementByOne中定义的数组在您使用第一个console.log进行日志记录时,其中只有未定义的值。我认为你真正想要做的只是在回调中返回值+1。

  2. 你在这里做了一个经典的值传递值传递错误;当他们第一次学习JS时,每个人都会犯这个错误。我建议您查看this one等帖子。简而言之,在.map回调内部,您正在改变传递给incrementByOne的数组,该数组与您使用第二个console.log注销的数组相同;这就是为什么值似乎已正确增加的原因。

答案 2 :(得分:0)

var array = [1,2,3,4,5,7];


function incrementByOne(arr) {
  arr = arr.map(v => v + 1);
  console.log(arr);
}



incrementByOne(array);

console.log(array);

// [undefined, undefined, undefined, undefined, undefined, undefined]

// [2, 3, 4, 5, 6, 8]

答案 3 :(得分:0)

嗯,以上所有答案都是正确的,但他们错过了最重要的一点。 JavaScript中有一个名为call by sharing的概念。

考虑以下代码:



var num= 3;
var json = {myValue : '10'};
var json2 = {myValue : '100'};

function callBySharing(a,b,c){
 a = a + 37;
 b = {myValue : 'new value'};
 c.myValue = 'new Value';
}

callBySharing(num,json,json2);

console.log(num);//3 *UNCHANGED*
console.log(json.myValue);//10 *UNCHANGED*
console.log(json2.myValue);//'new Value' *CHANGED*




所以你所做的与json.myvalue中发生的事情相同;您正在尝试更新整个对象并将其替换为新值。因此,代码中的一个非常简单的更改就是为您执行此操作:



var array = [1,2,3,4,5,7];


function incrementByOne(arr) {
  arr.map(function(value, index, array){
    arr[index] = arr[index] +1;
  
  
  });
  console.log(arr);
}



incrementByOne(array);

console.log(array);




我刚刚将arr = arr.map()....部分替换为arr.map().....

这样做,它将函数更改为json2.myValue示例case。

那么2之间的区别是什么:JS允许你更新对象中的项而不是整个对象。通过上面说的代码更改,你正在更新arr的各个值而不是用new替换整个对象值。当我与它混淆时,我才从SO中学到这个概念。所以我要链接帖子(Is JavaScript a pass-by-reference or pass-by-value language?

希望这有帮助!