Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

JavaScript properties

  • Loading branch information...
commit b4fd335f0683e89e70fbf203559fe1d9e25f07bd 1 parent afb8efd
@johnwakley authored
Showing with 136 additions and 4 deletions.
  1. +4 −3 spec/AboutObjects.js
  2. +132 −1 spec/AboutObjectsInECMAScript5.js
View
7 spec/AboutObjects.js
@@ -118,9 +118,10 @@ describe("about JavaScript Objects", function() {
// **Constructors and Prototypes**
//
// Every function you define automatically gets a `prototype` property, which
- // holds an object--the prototype of the function. This prototype gets
- // a `constructor` property, which points back at the function to which
- // it belongs.
+ // holds an object--the prototype of the function. The prototype acts like the
+ // object's parent.
+ // The prototype also gets a `constructor` property, which points back at the
+ // function to which it belongs.
//
describe("about constructors and prototypes", function() {
it("should show prototypal differences between object instance types", function() {
View
133 spec/AboutObjectsInECMAScript5.js
@@ -5,7 +5,7 @@
// ECMAScript 5, working with JavaScript objects is now more succinct.
//
// *Reference*
-// - http://killdream.github.com/blog/2011/10/understanding-javascript-oop/
+// - http://killdream.github.io/2011/10/09/understanding-javascript-oop.html
// - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create
//
"use strict";
@@ -90,6 +90,136 @@ describe("about ECMAScript 5 Objects", function() {
// delete foo.p;
});
});
+
+ //
+ // **Object Properties**
+ // Properties on objects are highly configurable. When creating a new property,
+ // you can use various 'descriptors' to define attributes on the property.
+ //
+ // Descriptors can be one of two types - data descriptors or accessor descriptors.
+ //
+ // *Data Descriptors*
+ // Data descriptors are those that hold concrete values, and therefore have an additional value parameter,
+ // describing the concrete data bound to the property:
+ //
+ // *`value`*
+ // The value of a property
+ //
+ // *Accessor Descriptors*
+ // Accessor descriptors, on the other hand, proxy access to the concrete value through getter and setter functions.
+ // When not set, they'll default to undefined.
+ //
+ // *`get ()`*
+ // A function called with no arguments when the property value is requested.
+ //
+ // *`set (new_value)`*
+ // A function called with the new value for the property when the user tries to modify the value of the property.
+ //
+ // *Descriptor Flags*
+ // Both types of descriptor contain flags, which define how a property is treated in the language.
+ // If a flag is not set, it's assumed to be false.
+ //
+ // *`writable`*
+ // Whether the concrete value of the property may be changed. Only applies to data descriptors.
+ //
+ // *`configurable`*
+ // Whether the type of descriptor may be changed, or if the property can be removed.
+ //
+ // *`enumerable`*
+ // Whether the property is listed in a loop through the properties of the object.
+ //
+ describe("about creating properties", function() {
+ it("should use `Object.defineProperty` to create a new property", function() {
+ var person = {};
+ Object.defineProperty(person, "name", { value: "john",
+ writable: true,
+ configurable: true,
+ enumerable: true });
+
+ expect(person.name).toEqual("john");
+ });
+
+ it("should use `Object.defineProperties` to create more than one property at a time", function() {
+ var person = {};
+ Object.defineProperties(person, { name: { value: "john",
+ writable: true,
+ configurable: true,
+ enumerable: true },
+
+ gender: { value: "male",
+ writable: true,
+ configurable: true,
+ enumerable: true }});
+
+ // Access a property bracket notation:
+ expect(person["name"]).toEqual("john");
+
+ // Access a property using dot notation:
+ expect(person.gender).toEqual("male");
+ });
+
+ it("should define properties in a more concise way", function() {
+ // You can ditch the verbosity by treating properties like key/value pairs.
+ // Use either bracket or dot notation.
+ // When creating properties this way, their writable, configurable and
+ // enumerable discriptor attributes default to false.
+ var person = {};
+ person.name = "john";
+ person["gender"] = "male";
+
+ expect(person["name"]).toEqual("john");
+ expect(person.gender).toEqual("male");
+ });
+
+ it("should delete a property", function() {
+ var person = {};
+ person.name = "john";
+ expect(person["name"]).toEqual("john");
+
+ delete person["name"];
+ expect(person["name"]).toEqual(undefined);
+ });
+
+ it("should use geters and setters", function() {
+ // Getters and setters are usually used in classical object oriented languages to provide encapsulation.
+ // They are not much needed in JavaScript, though, given how dynamic the language is.
+ // At any rate, they allow you to proxy the requests for reading a property value or setting it, and decide how to handle each situation.
+ //
+ // First, let's set the first and last names of our friend, as concrete data properties:
+ var person = {};
+
+ Object.defineProperty(person, "firstName", { value: "john",
+ writable: true });
+
+ Object.defineProperty(person, "lastName", { value: "lennon",
+ writable: true });
+
+ // Then we can define a common way of accessing and setting both of those values at the same time — let's call it `name`:
+
+ // Returns the full name of object.
+ function getFullName() {
+ return this.firstName + " " + this.lastName;
+ }
+
+ // Sets the name components of the object, from a full name.
+ function setFullName(newName) {
+ var names = newName.trim().split(/\s+/);
+ this.firstName = names["0"] || "";
+ this.lastName = names["1"] || "";
+ }
+
+ Object.defineProperty(person, "name", { get: getFullName,
+ set: setFullName,
+ configurable: true,
+ enumerable: true });
+
+ expect(person.name).toEqual("john lennon");
+
+ person.name = "paul mccartney";
+ expect(person.firstName).toEqual("paul");
+ expect(person.lastName).toEqual("mccartney");
+ });
+ });
});
// TODO:
@@ -97,6 +227,7 @@ describe("about ECMAScript 5 Objects", function() {
// - what about the constructor/init method?
//
// - Inheritance (http://stackoverflow.com/questions/8449343/instanceof-equivalent-for-object-create-and-prototype-chains)
+// - 1.8 listing properties
// - Using object literals as templates
// - Classical inheritance with Object.create (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create)
// - be wary of this problem:
Please sign in to comment.
Something went wrong with that request. Please try again.