Tuesday, June 30, 2015

JavaScript Objects

 object ⇔ {prop1, prop2, prop3, ... , propN}, (property ⇔ name:value)

A JavaScript object is a collection of properties, each of which has a name and a value. Since property names are strings, we say that an object maps string to values. In computer science, a data structure mapping string to values is named "hash", "hashmap", "hashtable", "dictionary" or "associative array". JavaScript objects are dynamic, as properties can be added and deleted after the object creation.

JavaScript object properties

An object property associates a name to a value. A property name may be any string. The property value may be any JavaScript value: a primitive value, an object, a function or (in ECMAScript5) a getter or a setter function.

JavaScript object property's attributes

Each property has associated data called attributes, which can assume true or false values in ECMAScript 5

attribute name attribute meaning attribute values
writable may I set the property's value true|false
enumerable may I iterate with for/in the property's name true|false
configurable may I delete property or modify its attributes true|false
JavaScript inheritance and object prototypes
In addition to keeping its own properties, a JavaScript object inherits the properties of another object, known as its “prototype.” This is called prototypal inheritance.
Terminology for objects

Here are some terms used to distinguish three categories of JavaScript objects:

native or built-in objects
A native object is an object or class of objects defined by the ECMAScript specification.
For example, arrays, functions, dates and regular expressions are native objects.
host object
A host object is an object defined by the host environment (such as a web browser) within which the JavaScript interpreter is embedded. For example HTMLElement objects are host objects. Host objects may also be native objects.
user-defined object
A user-defined object is an object created during execution of JavaScript code.
Terminology for object properties
own property
An own property is a property defined directly on an object
inherited property
An inherited property is a property defined by an object’s prototype object

1. JavaScript Object Creation

Three ways to create objects:
  • with object literals notation
  • with the new keyword
  • with the Object.create() function
Creating objects with literal notation
An object literal is a comma-separated list of properties enclosed within curly braces. Each property is a colon separated 'name:value' pair.
An object literal expression creates a new object each time it is evaluated.
var object = {}; // object with no (own) properties

var location = { latitude: '53.349805', longitude: '-6.260310' }; // object with two (own) properties

// object with four (own) properties
var umaThurman = {
   firstname: 'Uma',
   lastname: 'Thurman',
   fullname: 'Uma Karuna Thurman',
   birth: {
      place: 'Boston',
      date: 'April 29, 1970'
   }
};
All objects created by object literals have the same prototype object, JavaScript code refers to this prototype object as Object.prototype.
Creating objects with new keyword
The new keyword followed by a constructor function invocation creates and initialize a new object. You can use language built-in constructor function or your own defined constructor function.
var object = new Object(); // create an empty object: same as {}
var array  = new Array();  // create an empty array: same as []
var date   = new Date();   // create a Date object with current date
var regexp = new RegExp("\\d"); // create a RegExp object  
Objects created using the new keyword and a constructor invocation use the value of the prototype property of the constructor function as their prototype. So new Object() creates an object inheriting from Object.prototype, new Array() creates an object inheriting from Array.prototype, new Date() creates an object inheriting from Date.prototype.
Creating objects with ECMAScript 5 Object.create() static function
ECMAScript 5 static function Object.create() creates a new object, using its first argument as the prototype of that object. Object.create() takes an optional second argument that describes the properties of the new object.
var object = Object.create(Object.prototype); // create an empty object: like {} or new Object().

var location = { latitude: '53.349805', longitude: '-6.260310' };
var foggyDewPub = Object.create(location); // foggyDewPub has the location object as its prototype

2. Querying and Setting Object Properties

To obtain the value of a property, use the dot (.) or square bracket ([]) operators.

  • If you use the dot operator, the right hand must be an identifier that names the property.
  • If you use the square bracket, the value within the brackets must a string containing a property name.
var umaThurman = {
    firstName: 'Uma',
    lastName: 'Thurman',
    'Social Security number': 'UT3 BS 3476'
};

console.log(umaThurman.firstName); // Uma
console.log(umaThurman["Social Security number"]); // UT3 BS 3476

To create or set a property, use a dot or square brackets on the left-hand side of an assignment expression:

var umaThurman = {
    firstName: 'Uma',
    lastName: 'Thurman',
};

umaThurman.fullName = 'Uma Karuna Thurman';
umaThurman["VAT identification number"] = '8759825UT';
2.1 Objects As Associative Arrays

The following two JavaScript expression have the same value:

 object.property
 object["property"]

The first syntax is similar to accessing a static field of a struct in C or an object in Java, the second syntax is similar to accessing an array indexed by strings. In fact JavaScript objects are associative arrays, also known as hash or map or dictionary.

JavaScript objects are associative arrays, as a consequence object properties must not be defined in advance and a program can create any number of properties in any object at runtime. Since strings are datatype and programs can evaluate strings at runtime, programs which want to define new properties on an object have to use the array notation, not the dot notation.

You can use an object to store (x,y) pairs data from user's input leveraging the array notation.

2.2 Property Access and Inheritance

JavaScript objects have a set of own properties, and they also inherit a set of properties from their prototype object. When you query the property x in the object o, the property is searched on that object and, if not found, it is searched on his prototype and if not found on the prototype of the prototype, until the Object object is reached.

var erectus = {} // erectus inherits object methods from Object.prototype
erectus.erectusBirth = 'erectus born 800,000 years ago'; // and has an own property erectusBirth.

// neanderthalensis inherits properties from erectus and Object.prototype
var neanderthalensis = Object.create(erectus); 
// and has an own property neanderthalensisBirth.
neanderthalensis.neanderthalensisBirth = 'neanderthalensis born 200,000 years ago'; 

// sapiens inherits properties from neanderthalensis, erectus, and Object.prototype
var sapiens = Object.create(neanderthalensis); 
sapiens.sapiensBirth = 'sapiens born 70,000 years ago'; // and has an own property sapiensBirth.

console.log(sapiens.sapiensBirth); // ... "sapiensBirth" is own property
console.log(sapiens.neanderthalensisBirth); // ... "neanderthalensisBirth" property is in sapiens's prototype
console.log(sapiens.erectusBirth); // ... "erectusBirth" property is in prototype's prototype

When you assign a property pName to an object, you creates or reassign an own property to the object. If the object has an inherited property holding the same name pName, the newly created own property hides that inherited property

var father = {fullName: 'Kirk Douglas'};
var son = Object.create(father); // it creates a son object
console.log(son.fullName); // "Kirk Douglas", it returns father's property
son.fullName = 'Michael Douglas'; // this hides father's property
console.log(son.fullName); // 'Michael Douglas'

3. Testing Object Properties

A JavaScript object is set of properties. If you want to check whether an object has a property with a given name, you can do this in four ways:

  • with the in operator
  • with the Object.prototype.hasOwnProperty() method
  • with the Object.prototype.propertyIsEnumerable() method
  • by querying the property name

The in operator check whether an object has an own or an inherited property

var obj = { firstname: 'Uma', lastname: 'Thurman' };
"firstname" in obj; // true: obj has an own property "firstname"
"fullname" in obj;  // false: obj doesn't have a property "full name"
"toString" in obj;  // true: obj has an inherited propery toString

The hasOwnProperty method check whether object has own prop with the given name

var obj = { firstname: 'Uma', lastname: 'Thurman' };
obj.hasOwnProperty("firstname"); // true: obj has an own property firstname
obj.hasOwnProperty("fullname");  // false: obj doesn't have a property fullname
obj.hasOwnProperty("toString");  // false: toString is an inherited property

The propertyIsEnumerable method checks whether object has own prop and is enumerable

var obj = Object.create({ firstname: 'Uma', lastname: 'Thurman' });
obj.fullname = 'Uma Karuna Thurman';
obj.propertyIsEnumerable("fullname");  // true: obj has an own enumerable property fullname
obj.propertyIsEnumerable("firstname"); // false: y is inherited, not own
Object.prototype.propertyIsEnumerable("toString"); // false: not enumerable

The property!==undefined query checks whether it has own or inherited property

var obj = { firstname: 'Uma', lastname: 'Thurman' };
obj.firstname !== undefined; // true: obj has a property 'firstname'
obj.toString !== undefined; // true: obj inherits a toString property
obj.fullname !== undefined; // false: obj doesn't have a property 'fullname'

// property!==undefined query is not useful to detect existing property set to undefined
var obj = { firstname: undefined }; // property set to undefined
obj.firstname !== undefined // false: property exists but is undefined
"firstname" in obj // true: the property exists

How to check for existence of null, undefined and falsy values

  • Use the query if(prop != null) instead of if(prop !== undefined) to test for undefined and null at one time.
  • Use the query if(obj.property) to distinguish between truthy and falsy values.
// check whether the object has a property whose value is not null or undefined
if (obj.firstname != null)
    alert("hello " + obj.firstname);
 
// check whether the object has a property whose value is not null, undefined, false, "", 0 or NaN
if (obj.firstname)
    alert("hello " + obj.firstname);    

4. Enumerating Object Properties

If you want to iterate through object properties use the for/in loop. If you want to obtain a list of all properties you can use certain ECMAScript 5 function.

Example 1 - The for/in loop iterate through all the object properties

The for/in loop executes the body of the loop once for each enumerable property (own or inherited) of the object, assigning the name of the property to the loop variable. For example:

var obj = {
   firstName: "Uma",
   lastName: "Thurman",
   birthdate: 'April 29, 1970'
};
for(propKey in obj) // Loop through the properties
   console.log(propKey); // prints firstName, lastName and birthDate, but not toString

The for/in loop enumerates own and inherited object properies and object's methods as well. You might want to filter the properties returned by for/in. Here is how to do so:

// enumerate own properties except inherited ones
for(prop in obj) {
   if (obj.hasOwnProperty(prop)) 
}

// enumerate properties but skip methods
for(prop in obj) {
   if (!typeof obj[prop] === "function")
}

Example 2 - Using for/in loop to iterate ONLY through own properties

var uma = { firstName: "Uma", lastName: "Thurman", job: "actress" };
var heir = Object.create(uma); // creating heir object inheriting from uma object
heir.firstName = 'Maya Ray'; // updating heir's firstName property
 
// iterating ONLY through own properties with heir.hasOwnProperty()
for (var key in heir) {
   if(heir.hasOwnProperty(key))
      console.log(key); // firstName 
}

ECMAScript 5 function to enumerate properties

  • Object.getOwnPropertyNames() returns an array of the names of own properties
  • Object.keys() returns an array of the names of the enumerable own properties

Example 3 - enumerating properties with Objects.key()

var uma = {
    firstName: "Uma",
    lastName: "Thurman",
    job: "actress"  
};    

var keys = Object.keys(uma); // get an array of property names for object uma
var values = []; // empty array for storing property values
for(var i = 0; i < keys.length; i++) { // for each index of the keys array
    var key = keys[i]; // get the key or property name 
    values[i] = uma[key]; // store the value of the property
}
console.log(values); // ["Uma", "Thurman", "actress"]

5. Object Attributes

5.1 Object prototype attribute

The prototype attribute of an object specifies object's prototype. An object's prototype attribute is set when the object is created. There are three ways to create an object and this affects the object's prototype.

object creation techniqueobject's prototype
literals notationObject.prototype
new keywordprototype of the constructor function
Object.create() functionobject first argument to the function

How to query the prototype of an object

  • The ECMAScript 5 Object.getPrototypeOf(obj) static function returns the prototype of the object argument.
  • Objects created with new keyword use the value of the prototype property of their constructor function as their prototype. These objects inherit a constructor property that refers to the constructor function, so you can determine the prototype with the expression obj.constructor.prototype.

How to determine whether an object is the prototype of another object

To determine whether one object is the prototype of or is part of the prototype chain of another object, you can use the Object.prototype.isPrototypeOf() method. For example:

 var father = { fullName: 'Kirk Douglas' };
 var heir = Object.create(father); // create an heir object
 console.log(father.isPrototypeOf(heir)); // true: heir inherits from father
 console.log(Object.prototype.isPrototypeOf(heir)); // true: heir inherits from Object.prototype
5.2 Object class attribute

Object’s class attribute is a string that gives informations about the type of the object.

How to set the class of an object? ECMAScript 3 and 5 provide no way to set this attribute.

How to query the class of an object? To query an object's class attribute you have to invoke Object.prototype.toString() method, the default toString() method that every object inherits from Object.prototype. If you want to invoke it you have to use the Function.call() method, because many classes of object redefine it with a more useful one.

Examples:

Objects created through native constructors have class attributes that match the names of their constructors

var obj = {};
console.log(Object.prototype.toString.call(obj)); // "[object Object]": "Object" class attribute

var str = 'hello JavaScript';
console.log(Object.prototype.toString.call(str)); // "[object String]": "String" class attribute
    
var arr =  [ 'Ford', 'Nissan', 'Toyota' ];
console.log(Object.prototype.toString.call(arr)); // "[object Array]": "Array" class attribute

For objects created through object literals or by Object.create() function and for objects created by your own constructor function the default toString() method returns a wrong class attribute "Object". There is no way to set the class attribute for your own classes of objects.

function MyConstructor(){}
var myObj = new MyConstructor(); // myObj is an object of class MyConstructor
console.log(Object.prototype.toString.call(myObj)); // "[object Object]": wrong "Object" class attribute
    
var array =  [ 'Ford', 'Nissan', 'Toyota' ];
var heir = Object.create(array); // array is an object of class Array
console.log(Object.prototype.toString.call(heir)); // "[object Object]": wrong "Object" class attribute

No comments :

Post a Comment