简体   繁体   English

构造函数和原型

[英]constructor and prototype

Can someone explain this? 有人可以解释一下吗?

function Foo() {
    this.x = 1;
    this.y = 2;
}

function FooProto() {
    this.arrow = 1;
    this.bow = 1;
}

document.writeln(Foo.prototype); // [object Object] 
document.writeln(Foo.prototype.constructor); // function Foo() { x =1; y=2; }

My understanding here is: Foo.prototype is an Object whose constructor property is Function Foo. 我的理解是:Foo.prototype是一个Object,其构造函数属性是Function Foo。 Foo.[[Prototype]] is Function.Prototype Foo。[[Prototype]]是Function.Prototype

obj = new Foo;
document.writeln(obj.constructor); // function Foo() { x =1; y=2; }
document.writeln(obj.constructor.prototype); // [object Object]

Foo.prototype = FooProto;

document.writeln(Foo.prototype); // function FooProto() { arrow = 1; bow = 2; }
document.writeln(Foo.prototype.constructor); // function Function() { [native code] }

Question 1: How did the look up using [[Prototype]] happen here. 问题1:如何使用[[Prototype]]进行查找。 I would appreciate if someone can explain this to me. 如果有人能向我解释,我将不胜感激。

document.writeln(obj.constructor); // function Foo() { x =1; y=2; } .. no change
document.writeln(obj.constructor.prototype); // function FooProto() { arrow = 1; bow = 2; }

anotherObj = new Foo;
document.writeln(anotherObj.constructor); // function Function() { [native code] }
document.writeln(anotherObj.constructor.prototype); // function Empty() {}

Question 2: Same question as Question 1. How did the Javascript interpreter perform the lookup? 问题2:与问题1相同的问题.Javascript解释器是如何执行查找的?

When explaining prototype-based code, it is much simpler to use Object.create to explain stuff. 在解释基于原型的代码时,使用Object.create来解释内容要简单得多。 Object.create is a function that receives a prototype object and creates a new instance object that has the prototype object as its [[prototype]] Object.create是一个函数,它接收一个原型对象并创建一个新的实例对象,该对象将原型对象作为其[[prototype]]

When looking up properties in an object is work like this: 在对象中查找属性时,工作方式如下:

Every object has its own and immutable [[prototype]] property inside. 每个对象都有自己的,不可变的[[prototype]]属性。 This property is secret and hidden, unless you are in Firefox, where you can get it via __proto__ . 这个属性是秘密和隐藏的,除非你在Firefox中,你可以通过__proto__获取它。

When reading a property up we first search for it in the object itself and if we don't find it there we recursively search for the object's [[prototype]]. 读取属性时,我们首先在对象本身中搜索它,如果我们在那里找不到它,我们递归搜索对象的[[prototype]]。

When writing a property we always write an own-property (we never mutate the [[prototype]], even if it also has the property we are setting). 编写属性时,我们总是编写一个自己的属性(我们永远不会改变[[prototype]],即使它也具有我们正在设置的属性)。

proto = {a:1};
child1 = Object.create(proto);
child2 = Object.create(proto);

child1.a = 2;

console.log(proto.a);  //1
console.log(child1.a); //2
console.log(child2.a); //1

When creating a function 创建功能时

Whenever we create a function object in Javascript, it comes with a prototype property already filled in. This prototype is an object (inheriting from Object.prototype) and has the constructor property set to the corresponding function. 每当我们在Javascript中创建一个函数对象时,它都会附带一个已经填充的prototype属性。这个prototype是一个对象(继承自Object.prototype)并且将constructor属性设置为相应的函数。

When instantiating an object using a function constructor (new Foo) 使用函数构造函数实例化对象时(new Foo)

A new object is created with the functions prototype as its [[prototype]] and the function is run o the object to initialize it. 使用函数prototype作为其[[prototype]]创建一个新对象,并在该对象上运行该函数以初始化它。


  1. I don´t really want to explain what is going on in the first case, since the Foo.prototype = FooProto; 我真的不想解释第一种情况发生了什么,因为Foo.prototype = FooProto; part doesn't really make sense and is probably not what you wanted to do (remember that prototypes should be objects, not functions) 部分没有意义,可能不是你想做的(记住原型应该是对象,而不是函数)

  2. As for the second case, changing the prototype property of the constructor function will only affect the future instances (anotherObj). 至于第二种情况,更改构造函数的prototype属性只会影响将来的实例(anotherObj)。 The [[prototype]] property of the already created objects is secret and immutable so there is nothing you can do to change them. 已创建对象的[[prototype]]属性是秘密且不可变的,因此您无法更改它们。

    • Note that if you want to dynamically change the prototype and existing objects (monkey-patching) you can do that by writing and overwriting values in the existing prototype object instead of replacing it with a new one. 请注意,如果要动态更改原型和现有对象(猴子修补),可以通过在现有原型对象中编写和覆盖值而不是用新的替换它来实现。

There're two concepts of prototype in Javascript. Javascript中有两个原型概念。 (I take it as a name collision in language design.) (我把它当作语言设计中的名字碰撞。)

  1. The prototype in the " prototype chain ". 原型链中的原型 It is a inside property as mentioned in the last answer. 它是最后一个答案中提到的内部属性。 The prefered way to access it is Object.getPrototypeOf . 访问它的首选方法是Object.getPrototypeOf

     var a = {}; Object.getPrototypeOf(a); // Object {} Object.getPrototypeOf(Object.getPrototypeOf(a)); // null, the top of prototype chain. Object.getOwnPropertyNames(Object.getPrototypeOf(a)); // the methods inherited 
  2. Every constructor (I think acutally every function declared) has a own property "prototype". 每个构造函数 (我认为所有声明的函数)都有自己的属性“prototype”。 It come to use in the new operator. 它在new运营商中使用。

The new operator does 2 steps. new操作员执行两个步骤。

  1. First is to create an object whose prototype (the 1st one, saying, [[Prototype]]) is assigned as the constructor's prototype (the 2nd one). 首先是创建一个对象,其原型(第一个,说,[[Prototype]])被指定为构造函数的原型(第二个)。
  2. Second is to run the constructor (looking up from prototype.constructor ) with taking the created object as implicit argument this . 二是运行的构造函数(从仰视prototype.constructor )与服用创建对象作为隐含参数this

Now to your case: 现在你的情况:

The first obj was created with its property [[Prototype]] ( proto in some engines) assigned as Foo.prototype. 第一个obj是使用其[[Prototype]]属性(某些引擎中的proto )创建的,分配为Foo.prototype。

obj.constructor === obj.__proto__.constructor === Foo.prototype.constructor === Foo
obj.constructor.prototype === Function.prototype

Note that the constructor is also a Function object. 请注意,构造函数也是Function对象。

Then you changed the prototype of Foo . 然后你改变了Foo的原型。 This changed the obj.constructor.prototype but not obj.constructor which has a different reference. 这改变了obj.constructor.prototype而不是obj.constructor ,它有不同的引用。 The anotherObj had a new [[Prototype]] from the following new operator. anotherObj从以下new运算符中获得了一个新的[[Prototype]]。

This question has been here for years. 这个问题已经存在多年了。 Following readers may be also confused as me. 以下读者可能也会像我一样困惑。 I recommendated the newly published book Speaking JavaScript from Dr. Axel Rauschmayer : 我推荐了Axel Rauschmayer博士新出版的“ Speaking JavaScript ”一书:

Terminology: The Two Prototypes 术语:两个原型

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

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