Can Read-Only Properties be Implemented in Pure JavaScript?
JavascriptBrowserJavascript Problem Overview
Looking at the mozilla documentation, looking at the regular expression example (headed "Creating an array using the result of a match"), we have statements like:
> input: A read-only property that reflects the original string against which the regular expression was matched. > >index: A read-only property that is the zero-based index of the match in the string.
etc... is it possible to create your own object in JavaScript which will have read-only properties, or is this a privilege reserved to built-in types implemented by particular browsers?
Javascript Solutions
Solution 1 - Javascript
With [any javascript interpreter that implements ECMAScript 5][1] you can use Object.defineProperty to define readonly properties. In loose mode the interpreter will ignore a write on the property, in strict mode it will throw an exception.
Example from [ejohn.org][2]:
var obj = {};
Object.defineProperty( obj, "<yourPropertyNameHere>", {
value: "<yourPropertyValueHere>",
writable: false,
enumerable: true,
configurable: true
});
[1]: http://kangax.github.io/compat-table/es5/#Object.defineProperty "show browser support" [2]: http://ejohn.org/blog/ecmascript-5-objects-and-properties/
Solution 2 - Javascript
Edit: Since this answer was written, a new, better way using Object.defineProperty
has been standardized in EcmaScript 5, with support in newer browsers. See Aidamina's answer. If you need to support "older" browsers, you could use one of the methods in this answer as a fallback.
In Firefox, Opera 9.5+, and Safari 3+, Chrome and IE (tested with v11) you can define getter and setter properties. If you only define a getter, it effectively creates a read-only property. You can define them in an object literal or by calling a method on an object.
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
If you already have an object, you can call __defineGetter__
and __defineSetter__
:
var myObject = {};
myObject.__defineGetter__("readOnlyProperty", function() { return 42; });
Of course, this isn't really useful on the web because it doesn't work in Internet Explorer.
You can read more about it from John Resig's blog or the Mozilla Developer Center.
Solution 3 - Javascript
It is possible to have read-only properties in JavaScript which are available via getter methods. This is usually called the 'Module' pattern.
The YUI blog has a good writeup of it: http://yuiblog.com/blog/2007/06/12/module-pattern/
Snippet from the post:
YAHOO.myProject.myModule = function () {
//"private" variables:
var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";
//"private" method:
var myPrivateMethod = function () {
YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
}
return {
myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty."
myPublicMethod: function () {
YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");
//Within myProject, I can access "private" vars and methods:
YAHOO.log(myPrivateVar);
YAHOO.log(myPrivateMethod());
//The native scope of myPublicMethod is myProject; we can
//access public members using "this":
YAHOO.log(this.myPublicProperty);
}
};
}(); // the parens here cause the anonymous function to execute and return
Solution 4 - Javascript
As readonly property or variable here it is.
As aidamina said, and here is a short code for testing, by the way, very usefull now that JQuery pretends deprecate the selector property.
<script>
Object.defineProperties(window, {
"selector": { value: 'window', writable: false }
});
alert (window.selector); // outputs window
selector ='ddd'; // testing because it belong to the global object
alert (window.selector); // outputs window
alert (selector); // outputs window
window.selector='abc';
alert (window.selector); // outputs window
alert (selector); // outputs window
</script>
So there you have a readonly property or variable tested.
Solution 5 - Javascript
Yes we can have read only property for an object in JavaScript. It can be achieved with private variable and object.defineProperty()
method,
See the following example which illustrates object having read only property,
function Employee(name,age){
var _name = name;
var _age = age;
Object.defineProperty(this,'name',{
get:function(){
return _name;
}
})
}
var emp = new Employee('safeer',25);
console.log(emp.name); //return 'safeer'
emp.name='abc';
console.log(emp.name); //again return 'safeer', since name is read-only property
Solution 6 - Javascript
Here's a link to Douglas Crockford's page on "Private Members in Javascript"....it would seem to me these would be read only if only getter methods are supplied, and no setters:
Solution 7 - Javascript
You will see that I have defined a setter and getter for color so it can be modified. The brand on the other hand becomes read-only once the object is defined. I believe this is the functionality you were looking for.
function Car(brand, color) {
brand = brand || 'Porche'; // Private variable - Not accessible directly and cannot be frozen
color = color || 'Red'; // Private variable - Not accessible directly and cannot be frozen
this.color = function() { return color; }; // Getter for color
this.setColor = function(x) { color = x; }; // Setter for color
this.brand = function() { return brand; }; // Getter for brand
Object.freeze(this); // Makes your object's public methods and properties read-only
}
function w(str) {
/*************************/
/*choose a logging method*/
/*************************/
console.log(str);
// document.write(str + "<br>");
}
var myCar = new Car;
var myCar2 = new Car('BMW','White');
var myCar3 = new Car('Mercedes', 'Black');
w(myCar.brand()); // returns Porche
w(myCar.color()); // returns Red
w(myCar2.brand()); // returns BMW
w(myCar2.color()); // returns White
w(myCar3.brand()); // returns Mercedes
w(myCar3.color()); // returns Black
// This works even when the Object is frozen
myCar.setColor('Green');
w(myCar.color()); // returns Green
// This will have no effect
myCar.color = 'Purple';
w(myCar.color()); // returns Green
w(myCar.color); // returns the method
// This following will not work as the object is frozen
myCar.color = function (x) {
alert(x);
};
myCar.setColor('Black');
w(
myCar.color(
'This will not work. Object is frozen! The method has not been updated'
)
); // returns Black since the method is unchanged
The above has been tested on Chromium Version 41.0.2272.76 Ubuntu 14.04 and yielded the following output: > Porche > Red > BMW > White > Mercedes > Black > Green > Green > function () { return color; } > Black
Solution 8 - Javascript
bob.js framework provides a way to declare read-only properties. Under the hood, it declares a private field and exposes the getter/setter functions for it. bob.js provides multiple ways of doing this same thing, depending on the convenience and specific goals. Here's one approach that uses object-oriented instance of the Property
(other approaches allow defining setters/getters on the object itself):
var Person = function(name, age) {
this.name = new bob.prop.Property(name, true);
var setName = this.name.get_setter();
this.age = new bob.prop.Property(age, true);
var setAge = this.age.get_setter();
this.parent = new bob.prop.Property(null, false, true);
};
var p = new Person('Bob', 20);
p.parent.set_value(new Person('Martin', 50));
console.log('name: ' + p.name.get_value());
console.log('age: ' + p.age.get_value());
console.log('parent: ' + (p.parent.get_value ? p.parent.get_value().name.get_value() : 'N/A'));
// Output:
// name: Bob
// age: 20
// parent: N/A
At the end, p.name.set_value
is not defined because that's a read-only property.
Solution 9 - Javascript
So, it will only work if it is not already defined but, you can use const to make a variable readonly.