JS标准中,内置对象的属性被划分成了3类:构造器属性(Properties of the ? Constructor)、原型对象属性(Properties of the ? Prototype Object)、实例属性(Properties of ? Instances)。乍一看,头晕脑胀。
我找到一条容易理解JS标准中相关问题的途径,就是把原型对象看作面向对象语言的class。通过这个办法,理解了JS对象的constructor、prototype、__proto__,详见一条容易理解JS对象的constructor、prototype、__proto__的途径_万物智能相联的博客-CSDN博客,在这篇文章中,又理解了标题中的3种属性。
一个类的名字classA在JS中不代表该类,而代表该类的构造函数。因此Object、Function、Number等名称代表的是Object类、Function类、Number类的构造函数,任何classA类的构造函数都由classA代表。
classA.prototype代表该classA类,只有函数才有prototype。
下面以Array内置对象为例来说明3种属性的区别。
设var v=[1,2,3],则v是Array类的实例。Array这个表达式指的是Array类的构造函数,它也是函数对象,视作类则派生自Function类。Array.prototype指的是Array类。
1)构造器属性:Array.isArray这个表达式很明显表示isArray就只是Array类的构造函数作为函数对象的属性,所以称为构造器的属性,此言不虚。构造函数的属性不是Array类的属性,故v.isArray就等于undefined
2)原型对象属性:Array.prototype.concat这个表达式是指concat是原型对象的属性,即concat是Array类的方法,故可以调用v.concat。当然也可以获取Array.prototype.concat。
3)实例的属性:与原型对象的属性非常相似,v是从Array类实例化而来,Array内置对象有个名为length的实例的属性,于是可以调用v.length,但是不能获取Array.prototype.length。就是说,实例的属性可以勉强看作是不允许修改的原型对象的属性。