为什么第一个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()知道迭代次数但是值会发生什么......
答案 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)
这里发生了一些事情:
传递给.map函数的回调应返回带有return关键字的值。如果您没有从回调中返回值,则默认返回值是未定义的。这就是为什么' arr'您在incrementByOne中定义的数组在您使用第一个console.log进行日志记录时,其中只有未定义的值。我认为你真正想要做的只是在回调中返回值+1。
你在这里做了一个经典的值传递值传递错误;当他们第一次学习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?)
希望这有帮助!