有人可以解释一下吗?
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解释器是如何执行查找的?
答案 0 :(得分:5)
在解释基于原型的代码时,使用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]]创建一个新对象,并运行该函数来初始化它。
我真的不想解释第一种情况发生了什么,因为
Foo.prototype = FooProto;
部分没有意义,可能不是你想做的事情(请记住原型应该是对象,而不是功能)
对于第二种情况,更改构造函数的prototype
属性只会影响将来的实例(anotherObj)。已创建对象的[[prototype]]属性是秘密且不可变的,因此您无法更改它们。
答案 1 :(得分:0)
Javascript中有两个原型概念。 (我把它当作语言设计中的名字碰撞。)
" 原型链中的原型"。
它是最后一个答案中提到的内部属性。访问它的首选方式是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
每个构造函数(我认为每个声明的函数)都有自己的属性" prototype"。它来自new
运算符。
new
运算符执行两个步骤。
- 首先创建一个对象,其原型(第一个,说,[[Prototype]])被指定为构造函数的原型(第二个)。
- 其次是运行构造函数(从
醇>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 :