与其他编程语言相比,数组在JavaScript中是相当有用的东西,而且并非没有完整的怪癖。
包括这个:
// Making a normal array.
var normalArray = [];
normalArray.length = 0;
normalArray.push(1);
normalArray[1] = 2;
normalArray; // returns [1, 2]
normalArray.length // returns 2
是的,以上是我们大家都知道的制作数组并用元素填充它们的方法,对吗? (暂时忽略normalArray.length = 0
部分)
但是为什么将相同的序列应用于不是纯粹数组的对象时,它看起来有点不同,并且其length
属性却有些偏离呢?
// Making an object that inherits from the array prototype (i.e.: custom array)
var customArray = new (function MyArray() {
this.__proto__ = Object.create(Array.prototype);
return this
});
customArray.length = 0;
customArray.push(1);
customArray[1] = 2;
customArray; // returns [1, 1: 2]
customArray.length // returns 1
不能完全确定这里发生了什么,但是有些解释将不胜感激。
答案 0 :(得分:1)
您要创建的数组不是纯数组(您可能已经知道)。它基本上是一个JavaScript对象,应该表现得像一个对象。
在将对象像数组一样对待时,您可以自行维护所有像数组一样的特征。
您特别需要为其分配一个length
属性,并且您正确地做到了。
接下来,应该使用push
中的Array.prototype
方法将一个元素插入到数组中并增加length
属性(如果有),因此将0递增为1。您去了,length
现在是1。
接下来,您使用Object
的属性赋值的文字表示法,类似于customArray['someProperty'] = 1
之类的东西。
虽然使用文字表示法,但是没有调用Array.Prototype
中的任何方法,因此customArray对象从不知道它的行为必须像Array,并且length属性不受影响。它的行为就像一个对象,您将得到所得到的。
请记住length
只是Array类的一个属性,此属性由Array上的每个方法适当地递增和递减。
注意:不建议使用类似数组的对象,完全由您来维护此类对象的索引和其他数组内容。
答案 1 :(得分:1)
这可能不是一个完美的答案,但是根据我对Javascript数组的理解,它们与通常的对象有些不同。 (主要是因为它保留了length属性,而Objects没有)。
因此,如果我们以您的代码为例:
var normalArray = [];
这是在Javascript中创建数组的正确方法。但是下一个呢?
var customArray = new (function MyArray() {
this.__proto__ = Object.create(Array.prototype);
return this
});
它们相同吗?让我们看看。
Array.isArray(normalArray); // true -> [object Array]
Array.isArray(customArray); // false -> [object Object]
因此很明显,尽管您继承了数组原型,但实际上并没有创建Array
类型的对象。它只是创建一个普通的JS对象,但带有继承的数组函数。这就是为什么在使用customArray.push(1);
设置值时会更新长度的原因。
但是由于您的customArray
只是一个常规对象,而对于常规JS对象,[]
表示法用于设置属性,因此不会更新长度(因为Objects
没有length
属性)
希望很清楚:)
答案 2 :(得分:0)
据我所知,您的功能存在问题:
return this
应该是
return (this);
只需修复您可能遇到的任何潜在错误。另一件事是您没有使用var
关键字来声明customArray
。这些错误可能会破坏您的代码。