我有两个数组子类:Nodes和Beacons。当我在它们的两个实例上运行.concat时,它会创建一个包含2个元素的新数组:整个节点数组实例和整个信标数组实例。我该怎么做才能使它按预期工作?
Nodes.js
mgm.Nodes = function() {
Array.apply(this, arguments);
this.fetch();
};
mgm.Nodes.prototype = Object.create(Array.prototype);
mgm.Nodes.prototype.constructor = mgm.Nodes;
mgm.Nodes.prototype.create = function(data) {
//mgm.Node is an object and should be fine to replace with Object for testing purposes
var node = new mgm.Node(data);
this.push(node);
return node;
};
mgm.Nodes.prototype.get = function(id) {
};
mgm.Nodes.prototype.fetch = function() {
var n = 20;
for (var i = 0; i < n; i++) {
var data = {
id: i,
attributes: {name: undefined,}
};
this.create(data);
}
};
mgm.Nodes.prototype.remove = function(node) {
return this.splice(this.indexOf(node), 1)[0];
};
mgm.Nodes.prototype.update = function(node) {
// TODO: bind this to node.on('save')
};
Beacons.js
mgm.Beacons = function() {
this.fetch();
};
mgm.Beacons.prototype = Object.create(Array.prototype);
mgm.Beacons.constructor = mgm.Beacons;
mgm.Beacons.prototype.create = function(data) {
//mgm.Beacon is an object and should be fine to replace with Object for testing purposes
var beacon = new mgm.Beacon(data);
this.push(beacon);
return beacon;
};
mgm.Beacons.prototype.fetch = function() {
this.create({x: 200, y: 150, fixed: true, tag: ''});
};
运行此结果会生成长度为2的数组(预期为21),其中第0个元素的长度为20:
var nodes = new Nodes();
var beacons = new Beacons();
console.log(nodes.concat(beacons));
答案 0 :(得分:2)
它创建一个包含2个元素的新数组:整个节点数组实例和整个信标数组实例。
那是因为它们不是数组实例。查看the concat
method做了什么来确定要连接的对象是否逐项连接:
如果E的[[Class]]内部属性的值是“Array”,那么
[迭代E并推送每个元素]
else [将E作为整体放在结果数组上]
您的Beacons
和Nodes
可能会继承Array.prototype
,但它们是简单的对象 - 没有特殊[[Class]],没有自动调整length
属性。顺便说一句,Array.apply(this, arguments);
无法按预期工作,它只是创建一个新数组。使用this.push.apply(this, arguments);
。
如何使其按预期工作?
您可以使用自己的实现覆盖concat
:
mgm.Nodes.prototype.concat = mgm.Beacons.prototype.concat = function concat(other) {
var O = Object(this),
A = new Array(), // new this.constructor() ?
n = 0,
items = [O];
items.push.apply(items, arguments);
while (items.length > 0) {
var E = items.shift();
if (typeof E.length == "number") { // not: Array.isArray(E)
var k = 0,
len = E.length;
while (k < len) {
var P = ""+k;
if (Object.prototype.hasOwnProperty.call(E, P)) {
var subElement = E[P];
A[n] = subElement;
n++;
}
k++;
}
} else { // E is not Array-like
A[n] = E;
n++;
}
}
return A;
};