I was reading this question about read-only properties, and I came upon this snippet:
var myObject = {
get readOnlyProperty() { return 42; }
};
alert(myObject.readOnlyProperty); // 42
myObject.readOnlyProperty = 5; // Assignment is allowed, but doesn't do anything
alert(myObject.readOnlyProperty); // 42
Now, I know to hide the scope, you can use an IIFE, to also make a variable or property "private", but what I don't understand is:
Why is assignment allowed, and if it's allowed, how can nothing happen? In this snippet there is no inferred scope, so I don't understand how something in JS can infer a private property.
I was reading this question about read-only properties, and I came upon this snippet:
var myObject = {
get readOnlyProperty() { return 42; }
};
alert(myObject.readOnlyProperty); // 42
myObject.readOnlyProperty = 5; // Assignment is allowed, but doesn't do anything
alert(myObject.readOnlyProperty); // 42
Now, I know to hide the scope, you can use an IIFE, to also make a variable or property "private", but what I don't understand is:
Why is assignment allowed, and if it's allowed, how can nothing happen? In this snippet there is no inferred scope, so I don't understand how something in JS can infer a private property.
Share Improve this question edited May 23, 2017 at 11:43 CommunityBot 11 silver badge asked Jun 17, 2015 at 20:00 Sterling ArcherSterling Archer 22.4k19 gold badges85 silver badges121 bronze badges 5- It's not "private", it's using the "get" keyword to run a function that returns the value whenever you reference the property. – Patrick Roberts Commented Jun 17, 2015 at 20:03
-
Add a
set readOnlyProperty()
function that throws an error to prevent assignment. – Barmar Commented Jun 17, 2015 at 20:04 - Couldn't the user just define a setter method and override this read-only aspect? – Sterling Archer Commented Jun 17, 2015 at 20:05
-
1
@SterlingArcher not if you
Object.freeze
it. If you do it with.definePropety
it's also safe (see configurable and writable) – Benjamin Gruenbaum Commented Jun 17, 2015 at 20:09 -
@SterlingArcher You can only use
set
/get
in literal object definitions, so you can't create a setter (using thisset
/get
literal syntax) without making a new object. You can redefine the property usingObject.defineProperty
, though (unless the property hasconfigurable: false
, or the object is frozen). – apsillers Commented Jun 17, 2015 at 20:12
2 Answers
Reset to default 6Why is assignment allowed, and if it's allowed, how can nothing happen? In this snippet there is no inferred scope, so I don't understand how something in JS can infer a private property.
Because assignments (before strict mode) never throw and making it throw would violate that invariant that people expect. While you can still override it (by making a setter and making that throw) this is the default behavior in JavaScript for properties. We don't like it but it is what it is.
If you use strict mode - you should get:
TypeError: setting a property that has only a getter
Getters and setters within object literal expressions are pure sugar over the Object.defineProperty()
used in ES5.
What a getter does is that it returns a certain value, when a property of a certain object is requested.
let obj = {};
obj.foo = 3; // I am SETTING a property value
obj.foo; // I am GETTING the property value
So whenever you define a getter
, every time you request a property, you get the value that that getter
returns.
So if you have
let obj = {};
Object.defineProperty(obj, 'readOnly', {
'get': function() { return 42; }
});
Or
let obj = {
get readOnly() { return 42; }
};
Your variable will always be 42, because it can only return that value. You can try to set that property to any value, but in the end it will always return 42.
To forbidden assignment, you can add a setter and make it throw Error