1

我有两个数组子类:节点和信标。当我在他们的两个实例上运行 .concat 时,它会创建一个包含 2 个元素的新数组:整个节点数组实例和整个信标数组实例。我应该怎么做才能使其按预期工作?

节点.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')
};

信标.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));
4

1 回答 1

2

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

那是因为它们不是数组实例。查看concat方法如何确定要连接的对象是否逐项连接:

如果 E 的 [[Class]] 内部属性的值为“Array”,则

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

else [将 E 作为一个整体放在结果数组中]

您的BeaconsandNodes可能继承自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;
};
于 2013-09-17T22:08:31.080 回答