Object Properties
There are a number of ways of attaching a property "a" to an object "myObject":
var myObject = {};
myObject.a = 2;
or
myObject["a"] = 2;
or
var myObject = {
a: 2
}
The Object.defineProperty function
Starting with EcmaScript5 (which is widely supported since the release of IE9), you can also add a property like this:
var myObject = {};
Object.defineProperty(myObject, "a", {
value: 2
});
So why would you want to do that? Well, this adds a bit more control to how the property behaves. (Note: A good way to run through these examples is with interactive "node", so you don't have to throw alerts or add console.log statements to inspect values, since myObject.a will print the value to the screen.)
By default this property is read-only:
myObject.a; // 2
myObject.a = 3; // Doesn't throw an error, but has no effect.
myObject.a; // 2
You can make the property writable by specifying this:
var myObject2 = {}
Object.defineProperty(myObject2, "a", {
value: 2,
writable: true
});
myObject.a; //2
myObject.a = 3;
myObject.a; //3
This throws a TypeException only if "use strict"; (or --use-strict for the node REPL) has been called. Otherwise the assignment fails silently.
Two other properties you can set are worth a look:
configurable: [true/false]
determines whether you can change these settings. It is a one-way street; you cannot change a property from configurable: false to configurable: true, because that would be changing its configuration. Interestingly, there is a loophole for "writable": you can make a field read-only after you've locked down configuration, but you cannot change it back.
enumerable: [true/false]
determines whether the property shows up in a statement like this:
for (var key in myObject) {...}
It also appears to determine whether the property shows up on a REPL. If you type the name of an object with a non-enumerable property, it shows up as "{}", but an enumerable property will display: "{ a: 1 }".
There are two additional functions available from Object, which allow you to lock down configuration for all properties at a stroke. Object.seal(someObject) sets configurable:false for all properties, and Object.freeze(someObject) does that and also makes the properties read-only, making the object immutable.
For example, let's lock down a normal JavaScript property.
>var car = {make: 'Honda'}
{ make: 'Honda' }
>car
{make: 'Honda'}
>car.make = 'Chevy'
'Chevy'
>car.make
'Chevy'
>Object.freeze(car)
{ make: 'Honda' }
>car.make = 'Dodge'
'Dodge'
>car.make
'Chevy'
Finally, there are formal getters and setters, much like in C#:
var myObject = {
get a() { return 1; }
}
On node, if you type myObject, you get this:
{ a: [Getter] }
And typing myObject.a gets you this:
1
So we now have a read-only property. We can add a setter as well:
var myObject = {
set a(value) { this._a_ = value; }
get a() { return this._a_; }
}
>myObject
{ a: [Getter/Setter] }
>myObject.a = 1;
{ a: [Getter/Setter], _a_: 1 }
>myObject.a
1
So now we can do all kinds of settery things, like constrain values to an acceptable range, or log changes.
By default this property is read-only:
myObject.a; // 2
myObject.a = 3; // Doesn't throw an error, but has no effect.
myObject.a; // 2
You can make the property writable by specifying this:
var myObject2 = {}
Object.defineProperty(myObject2, "a", {
value: 2,
writable: true
});
myObject.a; //2
myObject.a = 3;
myObject.a; //3
This throws a TypeException only if "use strict"; (or --use-strict for the node REPL) has been called. Otherwise the assignment fails silently.
Two other properties you can set are worth a look:
configurable: [true/false]
determines whether you can change these settings. It is a one-way street; you cannot change a property from configurable: false to configurable: true, because that would be changing its configuration. Interestingly, there is a loophole for "writable": you can make a field read-only after you've locked down configuration, but you cannot change it back.
enumerable: [true/false]
determines whether the property shows up in a statement like this:
for (var key in myObject) {...}
It also appears to determine whether the property shows up on a REPL. If you type the name of an object with a non-enumerable property, it shows up as "{}", but an enumerable property will display: "{ a: 1 }".
There are two additional functions available from Object, which allow you to lock down configuration for all properties at a stroke. Object.seal(someObject) sets configurable:false for all properties, and Object.freeze(someObject) does that and also makes the properties read-only, making the object immutable.
For example, let's lock down a normal JavaScript property.
>var car = {make: 'Honda'}
{ make: 'Honda' }
>car
{make: 'Honda'}
>car.make = 'Chevy'
'Chevy'
>car.make
'Chevy'
>Object.freeze(car)
{ make: 'Honda' }
>car.make = 'Dodge'
'Dodge'
>car.make
'Chevy'
As usual, the assignment fails silently unless in strict mode, in which case you get a type error when you try to assign to the (now) read only property
Getters and Setters
Finally, there are formal getters and setters, much like in C#:var myObject = {
get a() { return 1; }
}
On node, if you type myObject, you get this:
{ a: [Getter] }
And typing myObject.a gets you this:
1
So we now have a read-only property. We can add a setter as well:
var myObject = {
set a(value) { this._a_ = value; }
get a() { return this._a_; }
}
>myObject
{ a: [Getter/Setter] }
>myObject.a = 1;
{ a: [Getter/Setter], _a_: 1 }
>myObject.a
1
So now we can do all kinds of settery things, like constrain values to an acceptable range, or log changes.
No comments:
Post a Comment