简体   繁体   English

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

[英]Does a new object in Javascript have a prototype property?

This is a purely trivial question for academic value: 对于学术价值来说,这是一个纯粹微不足道的问题:

If I create a new object, either by doing: 如果我创建一个新对象,可以通过执行以下操作:

var o = { x:5, y:6 };

or 要么

var o = Object.create({ x:5, y:6 });

when I query the o.prototype property, I get undefined . 当我查询o.prototype属性时,我得到了undefined I thought that any newly created object automatically inherits the Object.prototype prototype. 我认为任何新创建的对象都会自动继承Object.prototype原型。

Furthermore, invoking toString() , (a method of Object.prototype ) on this object works just fine, implying that o does inherit from Object.prototype . 此外,在此对象上调用toString()Object.prototype的方法)工作得很好,这意味着o确实从Object.prototype继承。 So why do I get undefined ? 那我为什么要undefined

There is a difference between instances and their constructors. 实例与其构造函数之间存在差异。

When creating an object like {a: 1} , you're creating an instance of the Object constructor. 在创建像{a: 1}这样的对象时,您将创建Object构造函数的实例。 Object.prototype is indeed available, and all functions inside that prototype are available: Object.prototype确实可用,并且该原型中的所有函数都可用:

var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true

But Object.create does something different. 但是Object.create做了不同的事情。 It creates an instance (an object), but inserts an additional prototype chain: 它创建一个实例(一个对象),但插入一个额外的原型链:

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

The chain will be: 该链将是:

Object.prototype  -  o  -  p

This means that: 这意味着:

p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true

To get the prototype "under" an instance, you can use Object.getPrototypeOf : 要在实例“下”获取原型,可以使用Object.getPrototypeOf

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

Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true

(Previously, you could access an instance's prototype with o.__proto__ , but this has been deprecated.) (以前,您可以使用o.__proto__访问实例的原型,但这已被弃用。)

Note that you could also access the prototype as follows: 请注意,您还可以按如下方式访问原型:

o.constructor === Object; // true

So: 所以:

o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true

This fails for Object.create -created objects because they do not have a constructor (or rather, their constructor is Object and not what you passed to Object.create because the constructor function is absent). 这对Object.create创建的对象失败,因为它们没有构造函数(或者更确切地说,它们的构造函数是Object而不是传递给Object.create因为构造函数不存在)。

Not a direct answer, but knowledge that everybody, who deal with inheritance in Javascript, should have. 不是一个直接的答案,而是知道每个人在Javascript中处理继承都应该有。

Prototype inheritance in Javascript is a tricky concept. Javascript中的原型继承是一个棘手的概念。 Up until now, it has been impossible to create an empty object (by empty I mean lacking even properties form Object via prototype). 到目前为止,创建一个空对象是不可能的(通过空表示我的意思是通过原型缺少表单对象的属性)。 So this means that creating a new object always had a link to the original Object prototype. 所以这意味着创建一个新对象总是有一个指向原始Object原型的链接。 However, according to the specification, the prototype chain of an object instance isn't visible, but some vendors have decided to implement their own proprietary object properties so that you could follow it, but it's highly recommended not to use it in production code. 但是,根据规范,对象实例的原型链是不可见的,但是一些供应商决定实现他们自己的专有对象属性,以便您可以遵循它,但强烈建议不要在生产代码中使用它。

The following sample code demonstrates just two ways of creating an object instance. 以下示例代码仅演示了创建对象实例的两种方法。

var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});

Even though you don't manually add object properties to empty curly braces, you still get automatically added prototype chain. 即使您没有手动将对象属性添加到空花括号,您仍然会自动添加原型链。 The same goes for the second example. 第二个例子也是如此。 To visualize it better, you can type those lines into Chrome console and then enter either someObject , otherObject or thirdObject to see details. 要更好地可视化,您可以在Chrome控制台中键入这些行,然后输入someObjectotherObjectthirdObject以查看详细信息。 Chrome shows the prototype chain by adding a proprietary property __proto__ which you can expand to see what is inherited and where it's from. Chrome通过添加专有属性__proto__来显示原型链,您可以展开该属性以查看继承的内容以及它的来源。 If you executed something like 如果你执行了类似的事情

Object.prototype.sayHello = function() {
  alert('hello');
};

you would be able to call it on all instances, by executing otherObject.sayHello() . 您可以通过执行otherObject.sayHello()在所有实例上调用它。

However, using something that was implemented quite recently (therefore not supported by all browsers), you can actually create a truly empty object instance (doesn't inherit even from Object itself). 但是,使用最近实现的东西(因此并不是所有浏览器都支持),您实际上可以创建一个真正空的对象实例(甚至不从Object本身继承)。

var emptyObject = Object.create(null);

When you enter it into Chrome console and then expand the emptyObject to see it's prototype chain, you can see that it doesn't exist. 当您将其输入Chrome控制台然后展开emptyObject以查看它的原型链时,您可以看到它不存在。 So even if you implemented the sayHello function to Object prototype, it would be impossible to call emptyObject.sayHello() since emptyObject does not inherit from Object prototype. 因此,即使您将sayHello函数实现为Object原型,也无法调用emptyObject.sayHello()因为emptyObject不会从Object原型继承。

Hope it helps a bit with the general idea. 希望它对一般的想法有所帮助。

JavaScript has two types of objects: function object and non-function object. JavaScript有两种类型的对象:函数对象和非函数对象。 Conceptually, all objects have a prototype ( NOT A PROTOTYPE PROPERTY ). 从概念上讲,所有对象都有一个原型不是原型性质 )。 Internally, JavaScript names an object's prototype as [[Prototype]] . 在内部,JavaScript将对象的原型命名为[[Prototype]]

There are two approaches to get any object (including non-function object)'s [[prototype]]: the Object.getPrototypeOf() method and the __proto__ property. 获取任何对象(包括非函数对象)的[[prototype]]有两种方法: Object.getPrototypeOf()方法和__proto__属性。 The __proto__ property is supported by many browsers and Node.js. 许多浏览器和Node.js都支持__proto__属性。 It is to be standardized in ECMAScript 6. 它将在ECMAScript 6中进行标准化。

Only a function (a callable) object has the prototype property . 只有一个函数(一个可调用的)对象具有prototype属性 This prototype property is a regular property that has no direct relationship with the function's own [[prototype]]. 这个prototype属性是一个常规属性,与函数自己的[[prototype]]没有直接关系。 When used as a constructor ( after the new operator), the function's prototype property will be assigned to the [[Prototype]] of a newly created object. 当用作构造函数(在new运算符之后)时,函数的prototype属性将被赋值给新创建的对象的[[Prototype]]。 In a non-function object, the prototype property is undefined . 在非函数对象中,prototype属性是未定义的。 For example, 例如,

var objectOne = {x: 5}, objectTwo = Object.create({y: 6});

Both objectOne and objectTwo are non-function objects therefore they don't have a prototype property . objectOne和objectTwo都是非函数对象,因此它们没有prototype属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM