难以手动走原型链 [英] Difficulty Manually Walking The Prototype Chain

查看:95
本文介绍了难以手动走原型链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想尝试手动移动几个对象的原型链,看看我在路上找到的东西。但是,我被困在我尝试的第一个。下面是代码:

  function MyObject(){} 
var x = new MyObject
console.log('----------------------------------------- ---');
console.log('x.constructor.name:'+ x.constructor.name);
console.log('x.constructor.prototype.constructor.name:'+ x.constructor.prototype.constructor.name);
console.log(x.constructor.prototype === Function.prototype?'Good guess。':'不,你错了。
console.log(x.constructor === MyObject?'Good guess。':'不,你错了。
console.log('----------------------------------------- ---');

上述代码在Google Chrome的开发人员工具控制台中生成以下输出:

  ------------------------------ -------------- 
x.constructor.name:MyObject
x.constructor.prototype.constructor.name:MyObject
不,你错了。
好​​猜。
--------------------------------------------

这是有意义的x的构造函数是MyObject函数,因为x被实例化使用new关键字MyObject遵循构造函数的定义)。因此,我理解第一行输出(注意:我开始计数从0开始的输出行)。第二行,但是,我困惑。我想知道MyObject的原型是什么。显然,它不是Function类型的对象,如第三行输出所示,它告诉我我错了。第四行输出只是加强了第一行的输出。



在一个更一般的注释,我假设正确的方式走一个对象的原型链从所讨论的对象到它的构造函数,然后从构造函数到构造函数的原型,假设这最后一个引用不为null。我假设这个两步过程(包括去构造函数,然后到构造函数的原型)应该重复,直到从构造函数到原型的空引用到达,从而表示原型链的结束。这似乎不工作,虽然,因为应用这种算法到上述情况只导致循环引用。



总之,我有两个问题: / p>


  1. 为什么是x.constructor === x.constructor.prototype.constructor(或者换句话说,为什么是循环引用)什么样的对象是x.constructor.prototype,反正(或者,换句话说,它是如何被实例化/它是从哪里来的)?

  2. 如何上述算法修正以正确地浏览对象x的原型链?

编辑
$ b

我在StackOverflow上遇到了一个类似的问题,这里,但它没有明确要求正确的方式走原型链。虽然...

解决方案

在JavaScript术语中,一个对象 的原型是指 a 继承属性的对象。基于标准的访问方式是使用 Object.getPrototypeOf

  var protoOfA = Object.getPrototypeOf(a); 

还有旧的方式,非标准,但由一些浏览器支持:

  var protoOfA = a .__ proto__; 

但是如果你有一个函数F, F.prototype 不引用 F 继承任何东西的对象。相反,它指代由F 创建的实例继承的对象:

 函数F {}; 
a = new F();
console.log(Object.getPrototypeOf(a)=== F.prototype); // true

定义函数时,将创建一个对象作为创建的实例的原型这个新对象存储在函数的原型属性中。



-



函数在许多方面都像对象(例如,它们可以有属性),但它们不像其他对象:

  console.log(typeof a); //object
console.log(typeof F); //function

他们的原型 )(这显然是 Chrome特定行为

  console.log(Object.getPrototypeOf(F)); //function Empty(){}
console.log(Empty); // ReferenceError:Empty is not defined

-



构造函数属性很奇怪。 翻译不在乎它 MDN说,令人困惑地


返回对创建实例原型的Object函数的引用。


此外,您可以更改对象上的构造函数的值,但这不会影响对象是什么或它的行为 - 它只是描述性的。



-



因此,为了回答您的问题:


为什么是x.constructor === x.constructor.prototype.constructor


没有好的理由。这是浏览器收敛的任意行为。


什么样的对象是x.constructor.prototype,反正


在此示例中,t的 x 的原型,与 Object .getPrototypeOf(x)。但一般来说,你不能依赖 x.constructor 或任何从它派生的任何东西,因为它是任意的。


如何纠正上述算法以正确地遍历对象x的原型链?




  for(var p = x; p!= null; p = Object.getPrototypeOf(p)){
//使用p
做某事}


I wanted to try manually walking the prototype chain of a few objects just to see what I find along the way. However, I got stuck on the first one that I tried. Here's the code:

function MyObject() { }
var x = new MyObject();
console.log('--------------------------------------------');
console.log('x.constructor.name: ' + x.constructor.name);
console.log('x.constructor.prototype.constructor.name: ' + x.constructor.prototype.constructor.name);
console.log(x.constructor.prototype === Function.prototype ? 'Good guess.' : 'No, you are wrong.');
console.log(x.constructor === MyObject ? 'Good guess.' : 'No, you are wrong.');
console.log('--------------------------------------------');

The above code results in the following output in the Developer Tools Console of Google Chrome:

--------------------------------------------
x.constructor.name: MyObject
x.constructor.prototype.constructor.name: MyObject
No, you are wrong.
Good guess.
--------------------------------------------

It makes sense that x's constructor is the MyObject function, since x was instantiated using the new keyword on MyObject (this follows from the definition of a constructor). Because of this, I understand the first line of output (note: I started counting lines of output from zero on up). The second line, however, confuses me. I would like to know what MyObject's prototype is. Apparently, it isn't an object of type Function, as indicated by the 3rd line of output, which tells me that I'm wrong. The fourth line of output just reinforces the output from the first line.

On a more general note, I assumed that the correct way to walk the prototype chain of an object would be to go from the object in question to its constructor, and then from the constructor to the constructor's prototype, assuming that this last reference is not null. I assumed that this two-step process (consisting of going to the constructor, and then to the constructor's prototype) should be repeated until a null reference from a constructor to a prototype is reached, thus signifying the end of the prototype chain. This doesn't seem to be working, though, since application of this algorithm to the above scenario just leads to circular references.

In summary, I have two questions:

  1. Why is x.constructor === x.constructor.prototype.constructor (or, in other words, why the circular references), and what kind of an object is x.constructor.prototype, anyway (or, in other words, how did it get instantiated / where did it come from)?
  2. How can the above algorithm be corrected in order to correctly walk the prototype chain for object x?

Edit

I came across a similar question on StackOverflow here, but it doesn't explicity ask the correct way to walk the prototype chain. It does point out the circular references, though...

解决方案

In Javascript terminology, an object a's "prototype" refers to the object from which a inherits properties. The standards-based way to access this is with Object.getPrototypeOf:

var protoOfA = Object.getPrototypeOf(a);

There's also the old way, non-standard but supported by some browsers:

var protoOfA = a.__proto__;

But if you have a function F, F.prototype does NOT refer the object from which F inherits anything. Rather, it refers to the object from which instances created by F inherit:

function F() {};
a = new F();
console.log(Object.getPrototypeOf(a) === F.prototype); // true

When you define a function, an object is created to serve as the prototype of instances created by that function, and this new object is stored in the function's prototype property.

--

Functions behave like objects in many ways (e.g., they can have properties) but they aren't exactly like other objects:

console.log(typeof a); // "object"
console.log(typeof F); // "function"

Their "prototypes" are ill-defined (example run in Chrome) (this is apparently a Chrome-specific behavior)

console.log(Object.getPrototypeOf(F)); // "function Empty() {}"
console.log(Empty);                    // ReferenceError: Empty is not defined

--

The constructor property is strange. The interpreter doesn't care about it. MDN says, confusingly:

Returns a reference to the Object function that created the instance's prototype.

Further, you can change the value of constructor on an object, but this has no effect on what the object is or how it behaves - it's merely descriptive.

--

So, to answer your questions:

Why is x.constructor === x.constructor.prototype.constructor

No good reason. This is arbitrary behavior browsers have converged on.

what kind of an object is x.constructor.prototype, anyway

In this example, t's x's prototype, the same as Object.getPrototypeOf(x). But in general you can't rely on x.constructor or anything derived from it, because it's arbitrary.

How can the above algorithm be corrected in order to correctly walk the prototype chain for object x?

for (var p = x ; p != null ; p = Object.getPrototypeOf(p)) {
  // do something with p
}

这篇关于难以手动走原型链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆