学习Array.prototype并计算其长度

时间:2013-06-22 07:32:11

标签: javascript

第一个:我最近知道Array.prototype本身就是一个数组([])。但令人惊奇的是它不是Array对象的实例。怎么可能?这是什么原因?

第二: Array.prototype有很多属性,但当你记录console.log(Array.prototype.length)时,输出为'0'。这里的原因是什么?我试过这个,结果相同

var x=[];
x['a']="b";
x['b']="c";
console.log(x.length)//output:0

如果你让我知道数组的元素和属性的区别

,那就太好了

4 个答案:

答案 0 :(得分:4)

首先,JavaScript中的对象继承自其他对象,而不是构造函数。因此声明“但令人惊奇的是它不是Array对象的实例”是错误的。

假设您有一个名为rectangle的对象,如下所示:

var rectangle = {
    height: 5,
    width: 10
};

rectangle.area = function () {
    return this.width * this.height;
};

现在我可以通过调用方法rectangle.area来计算这个矩形的面积。但是,我想创建一个具有不同widthheight的新矩形。这就是我要做的事情:

var rectangle2 = Object.create(rectangle);

rectangle2.height = 8;
rectangle2.width = 20;

alert(rectangle2.area());

此处对象rectangle2继承自对象rectangle。所以你看到对象实际上是从其他对象继承的,而不是从构造函数继承的。阅读以下主题以获取更多详细信息:

Questions regarding prototype function

当您使用new关键字进行函数调用之前,JavaScript会创建一个继承自函数prototype的新对象。因此,实例实际上继承自prototype

如果对象a位于对象b的原型链中,则对象b仅从对象a继承。这是我们有isPrototypeOf方法的原因。


接下来要记住的是instanceof运算符并不意味着什么。它可以用JavaScript实现,如下所示:

function instanceOf(obj, func) {
    return Object.prototype.isPrototypeOf.call(func.prototype, obj);
}

因此,只有当一个对象继承自该函数的prototype时,才能清楚地看到一个对象有资格作为函数的“instance”

这就是Array.prototype instanceof Array返回false的原因 - 对象无法从自身继承。

有关instanceof运算符如何工作的详细信息,请阅读以下主题:

JavaScript inheritance and the constructor property


最后,数组的length属性总是比数组的最大数字索引多一个。例如:

var a = [];
alert(a.length); // 0
a[99999] = null;
alert(a.length); // 100000

这就是Array.prototype.length 0的原因 - Array.prototype没有数字键。但是,如果为其分配数字键,则length属性将相应更改:

Array.prototype[99999] = null;
alert(Array.prototype.length); // 100000

同样适用于x - 属性"a""b"不是数字。因此它们不会影响数组的length


顺便说一句,如果你对原型继承感兴趣,那么你应该阅读Why Prototypal Inheritance Matters上的博客文章。

答案 1 :(得分:4)

  

我最近知道Array.prototype本身就是一个数组([])。

你是对的,它是一个数组。规范在§15.4.4, Properties of the Array Prototype Object中说明:

  

Array原型对象本身就是一个数组;其[[Class]]"Array",其length属性(初始值为+0)和15.4.5.1中描述的特殊[[DefineOwnProperty]]内部方法}。


  

但令人惊奇的是它不是Array对象的实例。怎么可能?这是什么原因?

如果您尝试Array.prototype instanceof Array,则结果确实为false。为什么?由于instanceof运算符的工作方式。它将对象的原型与构造函数的prototype属性的值进行比较 即在这种情况下它确实

Object.getPrototypeOf(Array.prototype) === Array.prototype

正如我们在此比较中已经看到的那样,我们正在尝试测试Array.prototype是否是自己的原型,这是不可能的。该规范也在同一段中提及:

  

Array原型对象的[[Prototype]]内部属性的值是标准的内置Object原型对象(15.2.4)。

Object.getPrototypeOf(Array.prototype) === Object.prototypeObject.prototype !== Array.prototype。因此,instanceof会产生false,但Array.prototype仍是一个数组。


  

Array.prototype有许多属性但是当你记录console.log(Array.prototype.length)时,输出为'0'。

作为0的值的

Array.prototype.length在规范中定义(参见上文)。

  

如果你让我知道数组的元素和属性的区别

,那就太好了

数组的元素是属性名称为正32位整数(或0)的属性。 属性是没有此类属性名称的任何其他属性。任何数组操作都不会考虑这些。

该规范在§15.4, Array Objects中提供了更精确的描述:

  

Array对象对某类属性名称进行特殊处理。当且仅当P等于ToString(ToUint32(P))P时,属性名称ToUint32(P)(以String值的形式)是数组索引 }不等于2 32 -1。属性名称为数组索引的属性也称为元素

所以你看,如果一个属性名转换为(字符串表示)一个无符号的32位整数并且仍然具有相同的值,那么它是一个数组索引,相关的值是该数组的一个元素。

规范连续

  

length属性的值在数值上大于名称为数组索引的每个属性的名称;

我们刚刚了解了哪些属性名称被认为是数组索引,那些可以转换为无符号整数的属性。根据该定义,"a"不是数组索引,因此

var x = [];
x['a'] = 42;

不会更改length属性。但是"3"是一个数组索引,所以

x["3"] = 42;

length属性更改为4

答案 2 :(得分:0)

当您将变量创建为

var x=[];
x[0] = 0; or x[x.length]=0; or x.push(0);

它是一个数组,它将具有length属性。 数组的成员可以使用索引(总是数字,即0,1,2,...)

来引用

但是当你创建一个变量

var x={};
x.key1= "value1"; or x["key1"]="value1";

它成为一个对象(JSON对象)。对象的成员将始终使用键引用。 比如x.key1,x,key2等...

您无法通过x.0或x.1等访问数组成员...

希望它可以帮到你

答案 3 :(得分:0)

关于第一点:数组是函数类型的对象。

console.log(Array);
function Array() { [native code] }

另一方面,Array.prototype是实例之间共享的方法的内部实现

所以,

console.log(Array.prototype);
[]

这就是console.log(Array.prototype.length)返回0的原因。这是一个空数组。

不要将Array.protoype视为Array的实例。它只是一个内部实现,您可以在其上调用原型对象的任何方法。

可以使用new运算符创建实例。并且所有实例都继承构造函数的原型对象,在本例中为Array。

var arr = new Array();

希望它澄清你的第一点。