2

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

第二:Array.prototype有很多属性但是当你登录ie时console.log(Array.prototype.length),输出是'0'。这是什么原因?我也试过了,结果是一样的

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

如果您让我知道数组的元素和属性的区别,那就太好了

4

4 回答 4

4

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

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

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

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

现在我可以通过调用方法来计算这个矩形的面积rectangle.area。但是说我想用不同的width和创建一个新的矩形height。这就是我要做的:

var rectangle2 = Object.create(rectangle);

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

alert(rectangle2.area());

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

关于原型函数的问题

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

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


接下来要记住的是,instanceof操作员实际上并没有任何意义。它可以在 JavaScript 中实现如下:

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

因此,您可以清楚地看到,只有从该函数的 继承的对象才有资格作为函数的“实例”prototype

Array.prototype instanceof Array这就是返回的原因false——对象不能从自身继承。

有关instanceof操作员如何工作的更多信息,请阅读以下线程:

JavaScript 继承和构造函数属性


最后,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数组的。


顺便说一句,如果您对原型继承感兴趣,那么您应该阅读我关于原型继承为何重要的博文。

于 2013-06-22T08:18:07.060 回答
4

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

你是对的,它是一个数组。规范在§15.4.4,数组原型对象的属性中说:

Array 原型对象本身就是一个数组;它[[Class]]"Array",并且它有一个length属性(其初始值为)和15.4.5.1+0中描述的特殊[[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。因此instanceofyield false,但Array.prototype仍然是一个数组。


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

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

如果您让我知道数组的元素和属性的区别,那就太好了

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

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

数组对象对某一类属性名称给予特殊处理。属性名称P(以字符串值的形式)是数组索引当且仅当ToString(ToUint32(P))等于PToUint32(P)不等于 2 32 -1。属性名称为数组索引的属性也称为元素

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

该规范与

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

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

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

不改变length属性。但是"3"是数组索引,所以

x["3"] = 42;

length属性更改为4

于 2013-06-22T09:10:19.253 回答
0

当您创建一个变量时

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

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

但是当你创建一个变量时

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

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

您不能通过 x.0 或 x.1 等访问数组成员...

希望对你有帮助

于 2013-06-22T08:19:30.857 回答
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();

希望它能澄清你的第一点。

于 2013-06-22T08:23:50.477 回答