第一个:我最近知道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
如果你让我知道数组的元素和属性的区别
,那就太好了答案 0 :(得分: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());
此处对象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.prototype
和Object.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();
希望它澄清你的第一点。