I don't understand why the following is happening:
function Class() {}
Class.prototype.foo = {a: 1};
Class.prototype.bar = 1;
x = new Class();
y = new Class();
y.foo.a = 2;
y.bar = 2;
x.foo.a; //2
x.ba开发者_Go百科r; //1
When I set y.foo.a
to 2, it seems to be performing the same operation as y.constructor.prototype.foo.a = 2
. Why would this be, given that y.bar = 2
doesn't affect y.constructor.prototype.bar
?
You are mixing prototype properties with properties that are local to the object instance. Using y.bar = 2
, you are assigning an instance property (bar
) to the instance y
. In interpreting a property (bar
) is first looked up within the instance itself. If it isn't found there, the lookup continues in the instances prototype. Now you assigned bar
to y
, so y.bar = 2
, but instance x
has no knowledge of it, so for x
the lookup continues using its prototype (that's prototype.bar
, still with value 1).
For y.foo.a
, there is no instance property foo
in y
, so it's looked up in its prototype. There it's found, and the property a
is assigned the new value. Because you are thereby changing a value of the Class.prototype
property foo
, it's also represented in x
.
If you want to change bar in its prototype (so originating from instance y
), you'll have to use the prototype of y
's constructor
(which is Class
):
y.constructor.prototype.bar = 2;
May mr Douglas Crockford can clarify things for you (jump to around minute 23 in the video for prototypal inheritance)?
You are reading y.foo
but assigning to y.bar
. These are different operations with different semantics. Setting y.foo.bar
must first read y.foo
: it looks for the value of foo
in y
, fails to find it, then looks in y
's prototype, discovers an object, and only then modifies that object. assigning y.bar simply looks up y and then modifies it. x.bar
and y.bar
then denote different objects, while x.foo
and and y.foo
denote the same object.
Reading an attribute does search in the prototype object, if it is not defined in the main object.
Setting an attribute does ever set it to the main object and NEVER to the prototype object.
Because of this, it is ever a bad idea to define something other than functions, or values that will never change in prototype objects.
To really understand what happens, I recommend you to experiment with the
__proto__
attribute. I know, not all browsers do support it, but it really helps you understand how prototyping in JavaScript works.
精彩评论