在JavaScript中,Object是所有实体的根,还是Function是根?
例如,在以下源objects-functions-and-prototypes-in.html中,首先作者说“Javascript中的每个实体都是一个对象”,后来它说“任何新对象只能作为函数的一个实例创建(即使你做'var a = new Object;',Object是一个函数btw)“。就我所见,作者基本上是自相矛盾的。
我在JavaScript上的许多其他资源中看到了同样的混乱评论。在Java中很容易,你知道任何类中的第一个实体Hierarchy是Object类,但在JavaScript中,我看到的只是混乱。
那么,有人可以澄清对象是先来还是功能?什么是根。
答案 0 :(得分:9)
我相信该行的结尾是Object.prototype
,这是一个对象。这就是让我这么想的原因:
Function.prototype; // the empty function object
Function.prototype.__proto__; // the default Object prototype
Object.prototype; // the default Object prototype
Object.prototype.__proto__; // null
ECMAScript 5.1规范如下所示:
在15.3.4 Properties of the Function Prototype Object中:
Function原型对象的[[Prototype]]内部属性的值是标准的内置Object原型对象
并在15.2.4 Properties of the Object Prototype Object
Object原型对象的[[Prototype]]内部属性的值为
null
答案 1 :(得分:8)
以下是Object.prototype
Object.prototype
所说的内容:
所有对象都从Object.prototype继承方法和属性,尽管它们可能被覆盖(除了具有null原型的Object,即Object.create(null))。
换句话说,Object
是几乎所有对象的根。 Function
和Function.prototype
都是Object.prototype
的孩子,function getPrototypes(obj) {
var protos = [],
parent = obj;
while ( true ) {
parent = Object.getPrototypeOf(parent);
if ( parent === null ) {
break;
}
protos.push(parent);
}
return protos;
}
本身就是> getPrototypes(3)
TypeError: Object.getPrototypeOf called on non-object
的孩子。
当我忽略构造函数时,我发现Javascript中的继承更容易理解,而是专注于原型链。对我而言,这样做既可以使问题更简单,也可以使答案更简单;问题如:
您可以使用此小片段轻松调查原型链(有用的文档MDN docs):
Object.prototype
根据此功能,here没有原型:
Object.create(null)
所以让我们把图元留下来。
对于对象,层次结构如下所示(子项缩进到其父项的右侧)。据我所知,真正的多重继承在Javascript中是不可能的,因此每个对象都有一个父对象,arguments
除外,它没有父对象:
Object.create(Object.prototype)
{}
Object.create({})
{}
[]
- 假设new Array()
是上一行的对象,而不是单独的新对象 function MyFunction() {}
Object.keys
Object.prototype.toString
Object.prototype.toString.call
getPrototypes
new MyFunction()
new String('abc')
Object.create(new String('abc'))
new Number(41)
new Boolean()
new Object(false)
/a/
X.prototype
X
这非常令人困惑!请注意,对于大多数情况,Number
不是Boolean
的原型!如果我们有一些更好的术语,情况可能会有所改善;但是......我们没有:(正如你所看到的,Object
和Function.prototype
之类的构造函数与它们生成的对象位于一个单独的子层次中。此外,Object.prototype
本身继承自constructor
的{{1}}继承。
如果您尝试这些示例,您还会发现使用var str1 = new String('abc'); var str2 = Object.create(str1);
属性是检查对象原型的一种不好的方法,原因有两个。给定str1 instanceof String
,原因如下:
对象可以是多个构造函数的实例:str1 instanceof Object
和constructor
都是真的。这不会反映在str1.contructor === String
属性中:Object.getPrototypeOf(str2).constructor === String
有时,我们找不到对象原型链中每个对象的构造函数:constructor
。这是因为String.prototype
属性是从str1.hasOwnProperty('constructor')
继承的:str2.hasOwnProperty('constructor')
和Object.getPrototypeOf(str1).hasOwnProperty('constructor')
都是假的,而str1.isPrototypeOf(str2)
是真的。幸运的是,您可以使用primitives方法代替:{{1}}为真。
答案 2 :(得分:3)
你误解了它。
Javascript中的所有内容(包括所有函数)都是一个对象。
但是,每个对象都是函数的实例。 (由对象的constructor
属性指定)