这对学术价值来说是一个纯粹的微不足道的问题:
如果我创建一个新对象,请执行以下操作:
var o = { x:5, y:6 };
或
var o = Object.create({ x:5, y:6 });
当我查询o.prototype
属性时,我得到undefined
。我认为任何新创建的对象都会自动继承Object.prototype
原型。
此外,在此对象上调用toString()
(Object.prototype
的方法)可以正常工作,这意味着o
确实从Object.prototype
继承。那我为什么要undefined
?
答案 0 :(得分:17)
实例与其构造函数之间存在差异。
创建{a: 1}
之类的对象时,您正在创建Object
构造函数的实例。 Object.prototype
确实可用,并且该原型中的所有函数都可用:
var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true
但Object.create
做了不同的事情。它创建一个实例(一个对象),但插入一个额外的原型链:
var o = {a: 1};
var p = Object.create(o);
链条将是:
Object.prototype - o - p
这意味着:
p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true
要在实例“下”获取原型,您可以使用Object.getPrototypeOf
:
var o = {a: 1};
var p = Object.create(o);
Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true
(以前,您可以使用o.__proto__
访问实例的原型,但这已被弃用。)
请注意,您还可以按如下方式访问原型:
o.constructor === Object; // true
所以:
o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true
这对Object.create
创建的对象失败,因为它们没有构造函数(或者更确切地说,它们的构造函数是Object
而不是传递给Object.create
的对象,因为构造函数不存在)。
答案 1 :(得分:4)
不是直接的答案,而是知道每个处理Javascript继承的人都应该有。
Javascript中的原型继承是一个棘手的概念。到目前为止,创建一个空对象是不可能的(通过空表示我的意思是通过原型缺少表单对象的属性)。所以这意味着创建一个新对象总是有一个指向原始Object原型的链接。但是,根据规范,对象实例的原型链是不可见的,但是一些供应商决定实现他们自己的专有对象属性,以便您可以遵循它,但强烈建议不要在生产代码中使用它。
以下示例代码演示了两种创建对象实例的方法。
var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});
即使您没有手动将对象属性添加到空花括号,您仍然会自动添加原型链。第二个例子也是如此。要更好地将其可视化,您可以在Chrome控制台中输入这些行,然后输入someObject
,otherObject
或thirdObject
以查看详细信息。 Chrome通过添加专有属性__proto__
来显示原型链,您可以展开该属性以查看继承的内容及其来源。如果您执行类似
Object.prototype.sayHello = function() {
alert('hello');
};
您可以通过执行otherObject.sayHello()
来在所有实例上调用它。
但是,使用最近实现的东西(因此并不是所有浏览器都支持),您实际上可以创建一个真正空的对象实例(甚至不从Object本身继承)。
var emptyObject = Object.create(null);
当您将其输入Chrome控制台,然后展开emptyObject
以查看其原型链时,您会发现它不存在。因此,即使您将sayHello
函数实现为Object原型,也不可能调用emptyObject.sayHello()
,因为emptyObject
不会从Object原型继承。
希望它对一般的想法有所帮助。
答案 2 :(得分:3)
JavaScript有两种类型的对象:函数对象和非函数对象。从概念上讲,所有对象都有原型( NOT A PROTOTYPE PROPERTY )。在内部,JavaScript将对象的原型命名为 [[Prototype]] 。
有两种方法可以获取任何对象(包括非函数对象)[[prototype]]: Object.getPrototypeOf()方法和 {{ 1}} 属性。许多浏览器和Node.js都支持__proto__
属性。它将在ECMAScript 6中进行标准化。
只有函数(可调用的)对象具有原型属性。这个原型属性是一个常规属性,与函数[[prototype]]没有直接关系。当用作构造函数(在new运算符之后)时,函数的prototype属性将被赋值给新创建的对象的[[Prototype]]。在非函数对象中,prototype属性是未定义的。例如,
__proto__
objectOne和objectTwo都是非功能对象,因此它们没有原型属性。