如何连接两个子类阵列?

时间:2013-09-17 21:24:28

标签: javascript

我有两个数组子类: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));

1 个答案:

答案 0 :(得分:2)

  

它创建一个包含2个元素的新数组:整个节点数组实例和整个信标数组实例。

那是因为它们不是数组实例。查看the concat method做了什么来确定要连接的对象是否逐项连接:

  

如果E的[[Class]]内部属性的值是“Array”,那么

     
    

[迭代E并推送每个元素]

  
     

else [将E作为整体放在结果数组上]

您的BeaconsNodes可能会继承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;
};