Can Read-Only Properties be Implemented in Pure JavaScript?

JavascriptBrowser

Javascript 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:

http://javascript.crockford.com/private.html

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionClaudiuView Question on Stackoverflow
Solution 1 - JavascriptAidaminaView Answer on Stackoverflow
Solution 2 - JavascriptMatthew CrumleyView Answer on Stackoverflow
Solution 3 - JavascriptRyan DohertyView Answer on Stackoverflow
Solution 4 - JavascriptAvenida GezView Answer on Stackoverflow
Solution 5 - JavascriptMohammed SafeerView Answer on Stackoverflow
Solution 6 - JavascriptDexygenView Answer on Stackoverflow
Solution 7 - JavascriptVincent CharetteView Answer on Stackoverflow
Solution 8 - JavascriptTengizView Answer on Stackoverflow
Solution 9 - JavascriptsldView Answer on Stackoverflow