繁体   English   中英

构造函数和原型

[英]constructor and prototype

有人可以解释一下吗?

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; }

我的理解是:Foo.prototype是一个Object,其构造函数属性是Function Foo。 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] }

问题1:如何使用[[Prototype]]进行查找。 如果有人能向我解释,我将不胜感激。

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() {}

问题2:与问题1相同的问题.Javascript解释器是如何执行查找的?

在解释基于原型的代码时,使用Object.create来解释内容要简单得多。 Object.create是一个函数,它接收一个原型对象并创建一个新的实例对象,该对象将原型对象作为其[[prototype]]

在对象中查找属性时,工作方式如下:

每个对象都有自己的,不可变的[[prototype]]属性。 这个属性是秘密和隐藏的,除非你在Firefox中,你可以通过__proto__获取它。

读取属性时,我们首先在对象本身中搜索它,如果我们在那里找不到它,我们递归搜索对象的[[prototype]]。

编写属性时,我们总是编写一个自己的属性(我们永远不会改变[[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

创建功能时

每当我们在Javascript中创建一个函数对象时,它都会附带一个已经填充的prototype属性。这个prototype是一个对象(继承自Object.prototype)并且将constructor属性设置为相应的函数。

使用函数构造函数实例化对象时(new Foo)

使用函数prototype作为其[[prototype]]创建一个新对象,并在该对象上运行该函数以初始化它。


  1. 我真的不想解释第一种情况发生了什么,因为Foo.prototype = FooProto; 部分没有意义,可能不是你想做的(记住原型应该是对象,而不是函数)

  2. 至于第二种情况,更改构造函数的prototype属性只会影响将来的实例(anotherObj)。 已创建对象的[[prototype]]属性是秘密且不可变的,因此您无法更改它们。

    • 请注意,如果要动态更改原型和现有对象(猴子修补),可以通过在现有原型对象中编写和覆盖值而不是用新的替换它来实现。

Javascript中有两个原型概念。 (我把它当作语言设计中的名字碰撞。)

  1. 原型链中的原型 它是最后一个答案中提到的内部属性。 访问它的首选方法是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. 每个构造函数 (我认为所有声明的函数)都有自己的属性“prototype”。 它在new运营商中使用。

new操作员执行两个步骤。

  1. 首先是创建一个对象,其原型(第一个,说,[[Prototype]])被指定为构造函数的原型(第二个)。
  2. 二是运行的构造函数(从仰视prototype.constructor )与服用创建对象作为隐含参数this

现在你的情况:

第一个obj是使用其[[Prototype]]属性(某些引擎中的proto )创建的,分配为Foo.prototype。

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

请注意,构造函数也是Function对象。

然后你改变了Foo的原型。 这改变了obj.constructor.prototype而不是obj.constructor ,它有不同的引用。 anotherObj从以下new运算符中获得了一个新的[[Prototype]]。

这个问题已经存在多年了。 以下读者可能也会像我一样困惑。 我推荐了Axel Rauschmayer博士新出版的“ Speaking JavaScript ”一书:

术语:两个原型

暂无
暂无

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

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