Javascript 数组连接不工作。为什么?

所以我创建了这个 jqueryui 小部件。它创建了一个 div,我可以将错误流转到其中。小部件代码如下:

$.widget('ui.miniErrorLog', {
logStart: "<ul>",   // these next 4 elements are actually a bunch more complicated.
logEnd:   "</ul>",
errStart: "<li>",
errEnd:   "</li>",
content:  "",
refs:     [],


_create: function() { $(this.element).addClass( "ui-state-error" ).hide(); },


clear: function() {
this.content = "";
for ( var i in this.refs )
$( this.refs[i] ).removeClass( "ui-state-error" );
this.refs = [];
$(this.element).empty().hide();
},


addError: function( msg, ref ) {
this.content += this.errStart + msg + this.errEnd;
if ( ref ) {
if ( ref instanceof Array )
this.refs.concat( ref );
else
this.refs.push( ref );
for ( var i in this.refs )
$( this.refs[i] ).addClass( "ui-state-error" );
}
$(this.element).html( this.logStart + this.content + this.logEnd ).show();
},


hasError: function()
{
if ( this.refs.length )
return true;
return false;
},
});

我可以向其中添加错误消息,以及对将进入错误状态的页面元素的引用。我用它来验证对话框。在“ addError”方法中,我可以传递一个 id,或者一个 id 数组,如下所示:

$( "#registerDialogError" ).miniErrorLog(
'addError',
"Your passwords don't match.",
[ "#registerDialogPassword1", "#registerDialogPassword2" ] );

但是当我传入一个 id 数组时,它就不工作了。问题出在以下几行(我认为) :

if ( ref instanceof Array )
this.refs.concat( ref );
else
this.refs.push( ref );

为什么这个 concat 不能工作。 this.refs 和 ref 都是数组。那么为什么这个 concat 不能工作呢?

奖励: 我在这个小部件中还做了什么蠢事吗? 这是我的第一个。

112236 次浏览

Concat 方法不会更改原始数组,您需要重新分配它。

if ( ref instanceof Array )
this.refs = this.refs.concat( ref );
else
this.refs.push( ref );

原因如下:

定义及用法

Concat ()方法用于连接两个或多个数组。

This method does not change the existing arrays, but returns a new 数组,包含已连接数组的值。

您需要将连接的结果分配回您所拥有的数组中。

详细介绍康斯坦丁 · 迪涅夫:

.concat()不会添加到当前对象,所以这将 没有工作:

foo.bar.concat(otherArray);

这将:

foo.bar = foo.bar.concat(otherArray);
dataArray = dataArray.concat(array2)

必须使用 = 重新赋值到 array,这样才能得到连接的值

let array1=[1,2,3,4];
let array2=[5,6,7,8];


array1.concat(array2);
console.log('NOT WORK :  array1.concat(array2); =>',array1);


array1= array1.concat(array2);
console.log('WORKING :  array1 = array1.concat(array2); =>',array1);

注意,如果您真的希望在使用 concat 函数时有一个可变的数组(我所说的可变是指它不创建新的数组,而是对现有的数组进行变异) ,那么您可以为该数组实例重新分配 concat 函数。当我需要这个的时候,我就这么做了。

let myArray = [];


myArray.concat= function(  toAdd){
if(Array.isArray(toAdd)){
for(let node of toAdd)
this.push(node);
}else
this.push(toAdd);
}

还有人提到,this.refs.concat(ref);分配并返回一个新数组,可以将其重新分配给对象: this.refs = this.refs.concat(ref);concat不修改任何一个参数数组。

However, probably more accurate here is to use push, which adds an element to the calling array in-place: this.refs.push(ref); (no reassignment with =--push returns the new array length which is usually ignored).

If you're adding multiple items, push accepts variable arguments, so you can spread an array onto it:

const arr = [0, 1, 2];
arr.push(3); // add one element
console.log(arr) // => [0, 1, 2, 3]
arr.push(4, 5); // add two elements
console.log(arr) // => [0, 1, 2, 3, 4, 5]
const toAdd = [6, 7, 8];
arr.push(...toAdd); // add an array
console.log(arr); // => [0, 1, 2, 3, 4, 5, 6, 7, 8]

concat可以通过重新分配产生类似的结果:

let arr = [0, 1, 2];
arr = arr.concat(3); // reassign with one new element
console.log(arr) // => [0, 1, 2, 3]
arr = arr.concat(4, 5); // reassign with two new elements
console.log(arr) // => [0, 1, 2, 3, 4, 5]
const toAdd = [6, 7, 8];
arr = arr.concat(toAdd); // reassign with a new array added
console.log(arr); // => [0, 1, 2, 3, 4, 5, 6, 7, 8]

concat is clearly less optimal for this use case but is useful to know about for others, particularly when immutability is needed (for example, when working with React state).

push变异的另一个方便之处是函数应该变异其参数:

const addOne = arr => { // contrived example
arr.push(1);
};
const arr = [];
addOne(arr);
console.log(arr); // => [1] as expected


const addOneBroken = arr => {
arr = arr.concat(1); // purely local reassignment!
};
addOneBroken(arr);
console.log(arr); // => still [1]

合并数组和项的另一个选项是扩展语法,类似于 concat:

let arr = [0, 1, 2];
const toAdd = [3, 4, 5];
const arr1 = [...arr, 3]; // add one item, similar to concat
console.log(arr1); // [0, 1, 2, 3]
const arr2 = [...arr, ...toAdd]; // add an array, similar to concat
console.log(arr2); // [0, 1, 2, 3, 4, 5]
arr = [-1, ...arr, 42, ...toAdd, 6, 7]; // build a new complex array and reassign
console.log(arr); // => [-1, 0, 1, 2, 42, 3, 4, 5, 6, 7]

The above can be done with chained concat calls:

let arr = [0, 1, 2];
const toAdd = [3, 4, 5];
arr = [-1].concat(arr).concat(42).concat(toAdd).concat(6).concat(7);
console.log(arr); // => [-1, 0, 1, 2, 42, 3, 4, 5, 6, 7]

Note that if you have an array you don't want to flatten during a push, just skip the ... spread:

const arr = [0, 1, 2];
const toAdd = [3, 4, 5];
arr.push(toAdd);
console.log(arr); // => [0, 1, 2, [3, 4, 5]]