Javascript中的新对象是否具有原型属性?

dku*_*ppi 16 javascript prototype-programming

对于学术价值来说,这是一个纯粹微不足道的问题:

如果我创建一个新对象,可以通过执行以下操作:

var o = { x:5, y:6 };
Run Code Online (Sandbox Code Playgroud)

要么

var o = Object.create({ x:5, y:6 });
Run Code Online (Sandbox Code Playgroud)

当我查询o.prototype属性时,我明白了undefined.我认为任何新创建的对象都会自动继承Object.prototype原型.

此外,对此对象的调用toString()(一种方法Object.prototype)工作正常,暗示o它继承自Object.prototype.那我为什么要这样undefined

pim*_*vdb 18

实例与其构造函数之间存在差异.

创建对象时{a: 1},您正在创建Object构造函数的实例.Object.prototype确实可用,并且原型中的所有功能都可用:

var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true
Run Code Online (Sandbox Code Playgroud)

Object.create确实有所不同.它创建一个实例(一个对象),但插入一个额外的原型链:

var o = {a: 1};
var p = Object.create(o);
Run Code Online (Sandbox Code Playgroud)

该链将是:

Object.prototype  -  o  -  p
Run Code Online (Sandbox Code Playgroud)

这意味着:

p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true
Run Code Online (Sandbox Code Playgroud)

要在实例"下"获取原型,您可以使用Object.getPrototypeOf:

var o = {a: 1};
var p = Object.create(o);

Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true
Run Code Online (Sandbox Code Playgroud)

(以前,您可以访问实例的原型o.__proto__,但已被弃用.)

请注意,您还可以按如下方式访问原型:

o.constructor === Object; // true
Run Code Online (Sandbox Code Playgroud)

所以:

o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true
Run Code Online (Sandbox Code Playgroud)

这对于Object.create创建的对象来说是失败的,因为它们没有构造函数(或者更确切地说,它们的构造函数Object不是您传递给的对象,Object.create因为构造函数不存在).

  • 你说"在创建像{a:1}这样的对象时,你正在创建一个Object构造函数的实例".说"你正在使用Object构造函数*创建一个新实例*"会不​​会更正确?我不是想抨击你的答案,而是试图理解这种语言Javascript. (2认同)

zat*_*ata 5

这不是一个直接的答案,而是每个在 Javascript 中处理继承的人都应该具备的知识。

Javascript 中的原型继承是一个棘手的概念。到目前为止,创建一个空对象是不可能的(我所说的空对象是指甚至缺少通过原型形成对象的属性)。所以这意味着创建一个新对象总是有一个到原始对象原型的链接。然而,根据规范,对象实例的原型链是不可见的,但是一些供应商已经决定实现他们自己的专有对象属性,以便您可以遵循它,但强烈建议不要在生产代码中使用它。

以下示例代码仅演示了创建对象实例的两种方法。

var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});
Run Code Online (Sandbox Code Playgroud)

即使您没有手动将对象属性添加到空花括号中,您仍然会自动添加原型链。第二个例子也是如此。为了更好地可视化它,您可以将这些行输入 Chrome 控制台,然后输入someObject,otherObjectthirdObject查看详细信息。Chrome 通过添加专有属性来显示原型链__proto__,您可以扩展该属性以查看继承的内容以及来自何处。如果你执行了类似的事情

Object.prototype.sayHello = function() {
  alert('hello');
};
Run Code Online (Sandbox Code Playgroud)

您可以通过执行在所有实例上调用它otherObject.sayHello()

然而,使用最近实现的东西(因此并非所有浏览器都支持),您实际上可以创建一个真正的空对象实例(甚至不从 Object 本身继承)。

var emptyObject = Object.create(null);
Run Code Online (Sandbox Code Playgroud)

当你将它输入到 Chrome 控制台,然后展开emptyObject查看它的原型链时,你会发现它不存在。因此,即使您将sayHello函数实现为 Object 原型,也无法调用,emptyObject.sayHello()因为它emptyObject不是从 Object 原型继承的。

希望它对总体思路有所帮助。


Yin*_*ing 5

JavaScript 有两种类型的对象:函数对象和非函数对象。从概念上讲,所有对象都有一个原型不是原型属性)。在内部,JavaScript 将对象的原型命名为[[Prototype]]

有两种方法可以获取任何对象(包括非函数对象)的[[prototype]]:Object.getPrototypeOf ()方法和__proto__属性。__proto__许多浏览器和 Node.js 都支持该属性。它将在 ECMAScript 6 中标准化。

只有函数(可调用)对象才具有原型属性。这个原型属性是一个常规属性,与函数本身的[[prototype]]没有直接关系。当用作构造函数时(在 new 运算符之后),函数的原型属性将被分配给新创建对象的 [[Prototype]]。在非函数对象中,原型属性是 undefined 。例如,

var objectOne = {x: 5}, objectTwo = Object.create({y: 6});
Run Code Online (Sandbox Code Playgroud)

objectOne 和 objectTwo 都是非函数对象,因此它们没有原型属性