开发者

Confusing prototype behavior in JavaScript

开发者 https://www.devze.com 2023-03-04 21:40 出处:网络
I don\'t understand why the following is happening: function Class() {} Class.prototype.foo = {a: 1}; Class.prototype.bar = 1;

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消