2012-02-26 113 views
3

有人可以解释这一点吗?构造函数和原型

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。 。富[[原型]]是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:你是怎么用[[原型]]发生在这里的抬头。如果有人能向我解释这一点,我将不胜感激。

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解释器如何执行查找?

回答

5

在解释基于原型的代码时,使用Object.create来解释东西要简单得多。 Object.create是接收原型对象,并创建一个具有原型对象作为其[[原型]]

当一个对象查找的属性是这样工作的一个新的实例对象的函数:

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

读取属性,我们首先在对象本身中搜索它,如果我们没有找到它,我们递归搜索对象的[[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属性设置为相应的功能。

当实例化使用函数构造(新的Foo)

新对象与功能prototype作为其创建[[原型]和运行该功能对象O到初始化它的对象。


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

  2. 至于第二种情况,更改构造函数的prototype属性只会影响将来的实例(anotherObj)。已经创建的对象的[[prototype]]属性是秘密和不可变的,所以你不能做任何改变。

    • 注意,如果你要动态地更改原型和现有的对象(猴子补丁),你可以做到这一点写在现有的原型对象覆盖,而不是用新的替换它的值。
0

有是在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. 构造(我认为实际上可以声明每个函数)具有自己的财产“原型”。它来用于new运营商。

new操作者确实2个步骤。

  1. 首先是创建一个对象,其原型(一日一说,[[原型]])被分配为构造器的原型(第2一个)。
  2. 其次是运行构造函数(从prototype.constructor查找),将创建的对象作为隐含参数this

我们您的情况:

第一obj用其指定为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]]。

此问题已在这里多年。以下读者也可能会把我困惑。我recommendated新近出版的书自Axel Rauschmayer先生说到博士的JavaScript

Terminology: The Two Prototypes