getter and setter inheritance

Mark S. Miller erights at google.com
Sun May 11 09:23:43 PDT 2008


2008/5/9 Kris Zyp <kris at sitepen.com>:
> A question of how inheritance/delegation should work with getters and
> setters was raised in a recent discussion.


Hi Kris,

The way I've been thinking of getters and setters is as if there are
two kinds of properties:

* A data property is defined by its current value, and whether the
value is writable. If the value is not writable, the property is
considered read-only.

* A procedural property is defined by a getter function and an
optional setter function. If there is no setter function, the property
is considered read-only.

For both kinds of properties, a property is further defined by its
property name, whether the property is enumerable, and whether the
property's definition is redefinable. (Where redefinable implies
deletable.) This would be reflected (so to speak) concretely in the
results of Object.getProperties and Object.getProperty, and in the
argument of Object.defineProperties.

  Object.getProperty(x, 'foo') => {value: 3, writable: false,
enumerable: false, redefinable: false}
  Object.getProperty(x, 'bar') => {getter: function(){return 3;},
enumerable: false, redefinable: false}

in which case x.foo and x.bar are behaviorally identical for
non-reflective clients.


> If there is an object A whose
> prototype is object B, and object A defines a getter for property foo, and
> object B defines a setter for property foo, and we write a value to A.foo,
> should the setter defined on object B be called?

I think it should be illegal to define a setter without defining a
getter. A procedural property should either have a getter or have a
getter and a setter.

Assuming B defines a getter and a setter for foo, and A defines a
getter for foo, the answer should be no. A's own foo is a read-only
procedural property that fully masks B's foo.


> If A didn't define any
> property on A, the setter would be inherited from B and would be called when
> A.foo was modified.

Yes.

> However, with the getter defined on A, should the
> inheritance stop at A, because there is a slot defined, or should it
> continue along the prototype chain because there was no setter defined for
> that property (nor plain value)?

Stop at A. s/slot/property


> The question also applies when the getter
> and setter are reversed. When a property is accessed and there is a setter
> defined, but no getter,

That case should be rejected as illegal.


> should we continue to down the prototype chain to
> find a getter or a plain value, or stop and return undefined? AFAICT, ES4
> doesn't explicitly define which is the correct behavior. Firefox follows the
> former behavior:
>
> B={set foo(v){foo = v},
>     get bar(){return "bar value"}}

B.foo should be rejected as illegal.

> A={get foo(){return "foo value"},
>     set bar(v){bar = v},
>     __proto__:B}

A.bar should be rejected as illegal.


-- 
    Cheers,
    --MarkM



More information about the Es4-discuss mailing list