在JavaScript中,如何使用[]运算符访问从Array继承的对象?

时间:2010-07-21 12:48:34

标签: javascript prototype prototypal-inheritance

我有一种情况,我需要创建一个继承自Array的新JavaScript对象。我使用以下代码:

// Create constructor function.
var SpecialArray = function () {};

// Create intermediate function to create closure upon Array's prototype.
// This prevents littering of native Array's prototype.
var ISpecialArray = function () {};
ISpecialArray.prototype = Array.prototype;
SpecialArray.prototype = new ISpecialArray();
SpecialArray.prototype.constructor = SpecialArray;


// Use Array's push() method to add two elements to the prototype itself.
SpecialArray.prototype.push('pushed proto 0', 'pushed proto 1');

// Use [] operator to add item to 4th position
SpecialArray.prototype[4] = 'direct [] proto to 4';

// Create new instance of Special Array
var x = new SpecialArray();

// Directly add items to this new instance.
x.push('pushed directly on X');
x[9] = 'direct [] to 9'

console.log(x, 'length: ' + x.length);

非常有趣的是,[]操作似乎没用,控制台输出是:

["pushed proto 0", "pushed proto 1", "pushed directly on X"] length: 3

我在这里缺少什么?

3 个答案:

答案 0 :(得分:4)

不可能继承Array类并以这种方式使用。 最适合您的解决方案是扩展数组类并按原样使用它。 还有两个我不喜欢的选项,但它们存在

答案 1 :(得分:3)

这是一直让人们吵闹的人之一。 length属性仅适用于有序元素。你不能扩展一个数组,然后插入一个任意的非sequitous键,并期望它工作。这是因为一旦扩展数组,就会破坏length属性和数组内容之间的关系。上面的Pointy链接非常好地解释了这一点。

为了证明这一点,请将其添加到示例的末尾:

console.log(x[4]);

正如您所看到的,您的条目存在且正确,它不是有序数组的一部分。

与javascript中的其他内容一样,Array对象只是一个带字符串键的关联数组。隐藏非数字,非连续键以欺骗您认为它是一个“正确的”数字索引数组。

Array对象的这种奇怪的混合设计意味着你可以做一些奇怪而美妙的事情,比如在同一个对象中存储有序和无序信息。我不是说这是个好主意,我只是说这是可能的。

正如您现在已经注意到,在迭代这样的结构时,不会出现对于有序信息的数组的一般用例有意义的非连续键。当你想获得键控信息时,它没那么有用,或者实际上没用。我敢说,如果排序不重要,你应该使用一个对象而不是一个数组。如果需要有序和无序都将数组存储为对象中的属性。

答案 2 :(得分:0)

The best way I have found to create a child prototype of an "Array" is to not make a child prototype of "Array" but rather create a child of an "Array-Like" prototype. There are many prototypes floating around that attempt to mimic the properties of an "Array" while still being able to "inherit" from it, the best one I've found is Collection because it preserves the ability to use brackets []. The major downfall is that it doesn't work well with non-numeric keys (i.e. myArray["foo"] = "bar") but if you're only using numeric keys it works great.

You can extend this prototype like this:

http://codepen.io/dustinpoissant/pen/AXbjxm?editors=0011

var MySubArray = function(){
  Collection.apply(this, arguments);
  this.myCustomMethod = function(){
    console.log("The second item is "+this[1]);
  };
};
MySubArray.prototype = Object.create(Collection.prototype);

var msa = new MySubArray("Hello", "World");
msa[2] = "Third Item";
console.log(msa);
msa.myCustomMethod();