[英]Javascript __proto__ output
Below are some examples showcasing the different behaviors of prototypal inheritance based on how the objects are defined and created. 下面是一些示例,展示了基于如何定义和创建对象的原型继承的不同行为。 I distinguish between the "prototype property" of an object, eg
someObject.prototype
and the "prototype reference" (which I think should refer to the object from which someObject
inherits?). 我区分对象的“原型属性”,例如
someObject.prototype
和“原型引用”(我认为应该引用someObject
继承的对象?)。
This seems to be the way to preserve the parent object's prototype property. 这似乎是保留父对象的prototype属性的方法。 Isn't this the recommended way of inheriting?
这不是推荐的继承方式吗?
// create object whose prototype reference is Object; add stuff.
var Parent = Object.create(Object);
Parent.a = "1";
Parent.f = function() { return true; };
// add stuff to prototype property
Parent.prototype.b = 1;
Parent.prototype.g = function() { return false; };
// create an object whose prototype reference is Parent (??)
var Child = Object.create(Parent);
console.log(Parent.__proto__) // [Function: Object]
console.log(Parent.prototype) // { b: 1, g: [Function] }
console.log(Child.__proto__) // { a: '1', f: [Function] }
console.log(Child.prototype) // { b: 1, g: [Function] }
I would have expected Child.__proto__
to be something naming Parent
in the same way Parent.__proto__
names Object
. 我原以为
Child.__proto__
是以Parent.__proto__
命名Object
方式命名Parent
东西。
We see that Child
's prototype reference points to the properties of Parent
rather than the properties of Parent.prototype
. 我们看到
Child
的原型引用指向Parent
的属性而不是Parent.prototype
的属性。 This is counterintuitive, to me at least, as I would have expected to see Parent.prototype
's properties b
and g
instead. 至少对我来说这是违反直觉的,因为我
Parent.prototype
期望看到Parent.prototype
的属性为b
和g
。
Mixed results. 结果喜忧参半
// use a constructor instead.
var Parent = function () {
this.a = "1";
this.f = function() { return true; };
}
// again, add stuff to prototype property.
Parent.prototype.b = 1;
Parent.prototype.g = function() { return false; };
// create an object whose prototype reference is Parent (??)
var Child = new Parent();
// create differently
var Sibling = Object.create(Parent);
console.log(Parent.__proto__) // [Function: Empty]
console.log(Parent.prototype) // { b: 1, g: [Function] }
console.log(Child.__proto__) // { b: 1, g: [Function] }
console.log(Child.prototype) // undefined
console.log(Sibling.__proto__) // [Function]
console.log(Sibling.prototype) // { b: 1, g: [Function] }
Here, Child
's prototype references Parents.prototype
's properties. 这里,
Child
的原型引用了Parents.prototype
的属性。 This is what I expected above? 这是我的预期吗?
On the other hand, Sibling
's prototype reference is now a function, which is the prototype reference of Parent
. 另一方面,
Sibling
的原型参考现在是一个函数,它是Parent
的原型参考。
This seems to be the way to preserve the parent object's prototype reference, but you lose its prototype property. 这似乎是保留父对象的原型引用的方法,但是你丢失了它的原型属性。
// create object constructor; add stuff.
var Parent = function () {
this.a = "1";
this.f = function() { return true; };
}
// add stuff to prototype property.
Parent.prototype.b = 1;
Parent.prototype.g = function() { return false; };
// create an object whose prototype reference is Parent (??)
var Child = function() {
this.c = "2";
};
// supposed Ad-hoc prototype inheritance
Child.prototype = Object.create(Parent.prototype)
console.log(Parent.__proto__) // [Function: Empty]
console.log(Parent.prototype) // { b: 1, g: [Function] }
console.log(Child.__proto__) // [Function: Empty]
console.log(Child.prototype) // {}
Is the method shown in Example 1 preferred since you have access to both the parent's prototype property, its own properties as well as Object
's properties/methods? 示例1中显示的方法是首选的,因为您可以访问父级的prototype属性,它自己的属性以及
Object
的属性/方法吗? I've read in other posts that some of these ways of inheriting should be equal...which is not true. 我在其他帖子中读到,这些继承方式中的一些应该是平等的......这不是真的。 Also, I've read other posts, eg here , that Example 3 is the way to go.
此外,我已阅读其他帖子,例如此处 , 示例3是要走的路。 Or perhaps I am just not sure what
__proto__
stands for... 或许我只是不确定
__proto__
代表什么......
Thanks for any clarification you might have for the differences between these mix and match situations! 感谢您对这些混合和匹配情况之间的差异所做的任何澄清!
I distinguish between the "prototype member" of an object, eg someObject.prototype and the "prototype reference"
我区分对象的“原型成员”,例如someObject.prototype和“原型引用”
Good terminology, and distinguishing them is the first step in understanding them and the difference between them . 良好的术语,区分它们是理解它们的第一步,以及它们之间的区别 。
(which I think should refer to the object from which someObject inherits?).
(我认为应该引用someObject继承的对象?)。
Exactly. 究竟。 In contrast to the
.prototype
member, you acess the protypte reference via Object.getPrototypeOf(obj)
or the non-standard .__proto__
property. 与
.prototype
成员相比,您通过Object.getPrototypeOf(obj)
或非标准.__proto__
属性访问protypte引用。
Example 1
例1
Isn't this the recommended way of inheriting?
这不是推荐的继承方式吗?
It's one way to do inheritance, and the most pure form of prototypical inheritance. 它是继承的一种方式,也是最纯粹的原型继承形式。 Notice that
Parent
and Child
are plain objects, no constructor functions are involved. 请注意,
Parent
和Child
是普通对象,不涉及构造函数。
// create object whose prototype reference is Object; add stuff. var Parent = Object.create(Object);
That's the first mistake: You're inheriting from the Object
function (which is based on the constructor pattern, see below). 这是第一个错误:你继承自
Object
函数 (基于构造函数模式,见下文)。 You should just do 你应该这样做
var Parent = {};
// or
var Parent = Object.create(Object.prototype);
// add stuff to prototype member Parent.prototype.b = 1; Parent.prototype.g = function() { return false; };
Yet, the .prototype
member is of no significance in this model of inheritance. 然而,
.prototype
成员在这种继承模型中并不重要。 It's just a normal property, in this case one inherited from Object
. 它只是一个普通的属性,在这种情况下,它继承自
Object
。 You're actually modifying the Object.prototype
object here (big no-no)! 你实际上是在这里修改
Object.prototype
对象(大Object.prototype
)!
// create an object whose prototype reference is Parent (??) var Child = Object.create(Parent);
Yes, that's what Object.create
does. 是的,这就是
Object.create
所做的。
[Example 1 / 1] I would have expected Child.
[例1/1]我原以为是Child。 proto to be something naming Parent in the same way Parent.
proto是以同样的方式命名Parent的东西。 proto names Object.
proto names对象。
It names Object
only because that is a named function. 它只命名
Object
因为它是一个命名函数。 There's no way to know the variable name Parent
from the object reference at runtime. 在运行时无法从对象引用中知道变量名称
Parent
。
[Example 1 / 2] We see that Child's prototype reference points to the members of Parent rather than the members of Parent.prototype.
[例1/2]我们看到Child的原型引用指向Parent的成员而不是Parent.prototype的成员。 This is counterintuitive, to me at least, as I would have expected to see Parent.prototype's members b and g instead.
至少对我来说这是违反直觉的,因为我原本希望看到Parent.prototype的成员b和g。
Yes, you're directly inheriting from the Parent
object. 是的,您直接从
Parent
对象继承。 .prototype
is insignificant as stated above. .prototype
是微不足道的。 Child.prototype === Object.prototype
(it's inherited twice). Child.prototype === Object.prototype
(它继承了两次)。
Example 2 - use a constructor instead.
示例2 - 改为使用构造函数。 Adding stuff to its prototype member.
将东西添加到其原型成员中。
// create an object whose prototype reference is Parent (??) var Child = new Parent();
[Example 2 / 1] Here, Child's prototype references Parents.prototype's members.
[例2/1]这里,Child的原型引用了Parents.prototype的成员。 This is what I expected above?
这是我的预期吗?
No. The new
operator creates a prototype reference to the value of the .prototype
member of the supplied constructor function - Parent.prototype
in this case. 否。
new
运算符创建对所提供构造函数的.prototype
成员的值的原型引用 - 在这种情况下为Parent.prototype
。
// create differently var Sibling = Object.create(Parent);
Again, here you're creating an object that has a prototype reference to a function. 同样,在这里,您要创建一个具有函数原型引用的对象。 Not what you want - instead use
不是你想要的 - 而是使用
var sibling = Object.create(Parent.prototype);
Parent.call(sibling); // optionall apply the constructor on it, like `new` does
[Example 2 / 2] On the other hand, Sibling's prototype reference is now a function, which is the prototype reference of Parent.
[例2/2]另一方面,兄弟姐妹的原型参考现在是一个函数,它是Parent的原型参考。
To be more exact, it is the Parent
function itself. 更确切地说,它是
Parent
函数本身。 That's why your Sibling
does inherit a .prototype
property. 这就是你的
Sibling
继承了.prototype
属性的原因。
Example 3 - This seems to be the way to preserve the parent object's prototype reference, but you lose its prototype member:
示例3 - 这似乎是保留父对象的原型引用的方法,但是您丢失了它的原型成员:
// supposed Ad-hoc prototype inheritance Child.prototype = Object.create(Parent.prototype)
This is necessary to set up the inheritance (prototype reference) chain for the constructor way. 这是为构造函数方式设置继承(原型引用)链所必需的。 It's the standard way to implement a "class" pattern in JavaScript.
这是在JavaScript中实现“类”模式的标准方法。
console.log(Parent.__proto__) // [Function: Empty] console.log(Parent.prototype) // { b: 1, g: [Function] } console.log(Child.__proto__) // [Function: Empty] console.log(Child.prototype) // {}
As you see here, both Parent
and Child
are functions - constructor functions to be exact. 如您所见,
Parent
和Child
都是函数 - 准确的构造函数。 You would need to invoke them: 你需要调用它们:
var childInstance = new Child();
console.log(childInstance) // {c: "2"}
console.log(childInstance.prototype) // undefined - it's not a constructor
console.log(childInstance.__proto__) // {} - the Child.prototype object
console.log(childInstance.__proto__.__proto__) // the Parent.prototype object
console.log(childInstance.__proto__.__proto__.__proto__) // the Object.prototype object
However, you forgot one step. 但是,你忘记了一步。
childInstance
does inherit b
and g
from Parent.prototype
, but does not have the a
and f
proeprties created in the Parent
constructor. childInstance
确实从Parent.prototype
继承了b
和g
,但没有在Parent
构造函数中创建的a
和f
proeprties。 For correct inheritance in the constructor model you also have to apply the Parent
constructor on each instance, preferably inside the Child
constructor: 为了在构造函数模型中进行正确的继承,您还必须在每个实例上应用
Parent
构造函数,最好是在Child
构造函数中:
function Child() {
Parent.call(this);
this.c = "2";
}
var childInstance = new Child();
console.log(childInstance) // {a: 1, f: [Function …], c: "2"}
To understand what Object.create
does, first you need to understand why it needs to do it. 要了解
Object.create
作用,首先需要了解它为什么需要这样做。
The classic examples of prototyping in JavaScript makes the prototype be an instance of the inherited object: JavaScript中原型设计的经典示例使原型成为继承对象的实例:
function Parent(field) {
this.field = field;
}
Parent.prototype.getField = function () { return this.field; }
function Child(field, field2) {
Parent.call(this, field);
this.field2 = field2;
}
Child.prototype = new Parent(null); // oops
Child.prototype.getField2 = function () { return this.field2; }
That "oops" line makes Child.prototype
have a field
, when we wanted it to only inherit the method getField
. 那个“oops”
Child.prototype
有一个field
,当我们希望它只继承方法getField
。 You can guess this is not hygienic (language-wise), and it can get messy with less trivial examples. 你可以猜测这不是卫生的(语言方面的),并且可能会因为不那么重要的例子而变得混乱。
A cleaner approach would be to instantiate a non-initialized Parent
: 更简洁的方法是实例化一个未初始化的
Parent
:
function inherit(parent) {
function temp() {
}
temp.prototype = parent.prototype;
return new temp();
}
Child.prototype = inherit(Parent);
The technique is to make a temporary constructor with the same prototype, such that when an object is created, no constructor initializations were done. 该技术是使用相同的原型制作临时构造函数,这样在创建对象时,不会进行构造函数初始化。 Effectively, only the prototype chain has been established.
实际上,只建立了原型链。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.