As it is said in the 8.1.1.2 section of the spec:
Immutable bindings do not exist for object Environment Records.
And:
Because properties can be dynamically added and deleted from objects, the set of identifiers bound by an object Environment Record may potentially change as a side-effect of any operation that adds or deletes properties. Any bindings that are created as a result of such a side-effect are considered to be a mutable binding even if the Writable attribute of the corresponding property has the value false.
So if I understand correctly that means that the following code should outputs 3:
Object.defineProperty(this, "prop", {
value: 1,
writable: false
});
console.log(prop); // 1
this.prop = 2;
console.log(prop); // 1
prop = 3;
console.log(prop); // Here.
But what is actually does output is 1.
Is it implementations' bug or what? I've tested in Chome's and Node.js's V8 and Firefox's SpiderMonkey and the result is 1 everywhere.
Could you please clarify to me why?
any operation that adds or deletes properties
Object.defineProperty(this, 'prop', { value: 3 });
console.log(prop);
In other words, "writable: false" means you can't [[Set]] it - you can't change it by assignment. However, it's still configurable, so you can still [[Define]] it.
@ljharb , but it still doesn't explain this part of the quote:
Any bindings that are created as a result of such a side-effect are considered to be a mutable binding even if the Writable attribute of the corresponding property has the value false.
Why after [[Set]]ting variable prop to 3 it behaves like immutable binding and is anyways eqals to 1?
Iām not sure what the intention was, but āmutableā means āchangeableā, not āassignableā.
Why after [[Set]]ting variable prop to 3 it behaves like immutable binding and is anyways eqals to 1?
Assignment to non-write properties in non-strict mode code are silently ignored. If you did the same assignment in strict mode it would throw an exception.
@ljharb , @allenwb
Let me try to explain what I mean.
First of all, object component is one of two components of the global Environment Record. It is represented by Global Object. So the Global Object is the binding object of the object component of the global Environment Record.
Because properties can be dynamically added and deleted from objects...
// dynamically adding the property to the Global Object
this.a = 1;
...the set of identifiers bound by an object Environment Record may potentially change as a side-effect of any operation that adds or deletes properties.
// so now we have the new identifier available
console.log(a); // 1
Any bindings that are created as a result of such a side-effect...
In this example such a binding is a
...are considered to be a mutable binding...
And yeah, here it goes:
// I can change the value of the binding
a = 2;
console.log(a); // 2 for real
So this part works the proper way. But:
are considered to be a mutable binding even if the Writable attribute of the corresponding property has the value false
So this means that if the a property of the global object has the writable attribute set to false:
Object.defineProperty(this, "a", {
value: 1,
writable: false
});
Then I must not be able to change it's value addressing it as a property of the Global Object:
this.a = 2; // must not work
console.log(this.a); // 1 (and it doesn't)
But I _must_ be able to change the value of the property addressing it via the binding:
a = 2; // must work!
console.log(a); // must be 2, but it's 1!
And I must be able to do so because of 2 reasons:
Immutable bindings do not exist for object Environment Records. At all. Immutable properties of the object Environment Records' binding objects do. But the bindings pointing to the corresponsive properties of such objects don't.
Could you please explain which part did I interpret incorrect? What exactly part do I understand wrong?
Thank you for your time.
It seems like this thread is a miscommunication about wording: "immutable binding" is a specific term used in environment records to refer to certain kinds of bindings, such as that created by const declarations. On the other hand, there are non-writable properties, which throw when written to in strict mode. Although, at a high level, these may be immutable (especially if made non-configurable, so you can't even redefine them), they're not included in what's referred to as "immutable bindings".
Maybe we should clarify the wording of this section somehow.
@littledan
It seems like this thread is a miscommunication about wording: "immutable binding" is a specific term used in environment records to refer to certain kinds of bindings, such as that created by const declarations.
Exactly. I thought that it might be any binding the value of which you can not change in any way.
But I still don't understand this part though:
are considered to be a mutable binding even if the Writable attribute of the corresponding property has the value false
Doesn't it finally mean that I must be able to change the value of the binding corresponding to non-writable property of the binding object of the corresponding Object Env.? This is the only question that bothers me for now.
Maybe we should clarify the wording of this section somehow.
And yeah, this would be great of you, if we would finally come to some concrete conclusion.
Doesn't it finally mean that I must be able to change the value of the binding corresponding to non-writable property of the binding object of the corresponding Object Env.? This is the only question that bothers me for now.
No, just because the binding itself isn't considered "immutable" in this particular piece of technical language doesn't mean you can necessarily change it.
Is anyone interested in proposing some new wording which may clarify things? @jmdyck ?
@littledan the clearest explanation for me from all out here. Thank you!