3

我有一种情况,我需要创建一个继承自 Array.js 的新 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

我在这里想念什么?

4

3 回答 3

4

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

于 2010-07-21T13:18:21.270 回答
3

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

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

console.log(x[4]);

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

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

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

正如您现在已经注意到的那样,在迭代这样的结构时,不会出现非顺序键,这对于有序信息的数组的一般用例是有意义的。当您想要获取密钥信息时,它的用处不大,或者实际上没用。我敢冒险,如果排序不重要,您应该使用对象而不是数组。如果您需要有序和无序将数组作为属性存储在对象中。

于 2010-07-21T13:12:40.283 回答
0

我发现创建“Array”的子原型的最佳方法是创建“Array”的子原型,而是创建“Array-Like”原型的子原型。有许多原型试图模仿“数组”的属性,同时仍然能够“继承”它,我发现最好的一个是Collection,因为它保留了使用括号的能力[]。主要的缺点是它不适用于非数字键(即myArray["foo"] = "bar"),但如果您只使用数字键,它会很好用。

你可以像这样扩展这个原型:

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();
于 2016-07-11T20:47:52.767 回答