Why Does Object.seal Allow User Setters To Still Work, But Disables Native Setters Like __proto__?
Solution 1:
Calling the __proto__
setter makes the engine internally call the SetPrototypeOf
procedure. From the spec:
B.2.2.1.2 set Object.prototype.proto
The value of the [[Set]] attribute is a built-in function that takes an argument proto. It performs the following steps:
- Let O be RequireObjectCoercible(this value).
- ReturnIfAbrupt(O).
- If Type(proto) is neither Object nor Null, return undefined.
- If Type(O) is not Object, return undefined.
- Let status be O.[SetPrototypeOf].
- ReturnIfAbrupt(status).
- If status is false, throw a TypeError exception.
If the object is sealed, the SetPrototypeOf
call returns false, because:
- If extensible is false, return false.
Setters which don't attempt to call setPrototypeOf
(internally or externally) will not throw an error. Object.seal
does not prevent setters from being called, but it prevents setters which actually try to add new properties (or change the object's prototype) from succeeding. Because your custom setter doesn't try to add new properties, no error is thrown; the _foo
property is put onto the object before it is sealed.
If you had called the setter for the first time after the object was sealed, before_foo
had been added, you would've seen an error in strict mode:
'use strict';
var o = {
getfoo() {
returnthis._foo
},
setfoo(val) {
this._foo = val
},
}
Object.seal(o)
o.foo = 10
In non-strict mode, assigning a new property to a sealed object will fail silently (but trying to change the prototype will throw an error):
var o = {
getfoo() {
returnthis._foo
},
setfoo(val) {
this._foo = val
},
}
Object.seal(o)
o.foo = 10console.log(o.foo);
Solution 2:
Sealing the object locks in the internal [[prototype]] link. You can't change it any more, regardless trough which method:
> Object.setPrototypeOf(Object.seal({}), {})
VM2817:1 Uncaught TypeError: #<Object> is not extensible
at Function.setPrototypeOf (<anonymous>)
at <anonymous>:1:8
This has nothing to do with getters/setters.
Post a Comment for "Why Does Object.seal Allow User Setters To Still Work, But Disables Native Setters Like __proto__?"