© Russ Ferguson and Keith Cirkel 2017
Russ Ferguson and Keith CirkelJavaScript Recipes10.1007/978-1-4302-6107-0_9

9. Working with Objects

Russ Ferguson and Keith Cirkel2
(1)
Ocean, New Jersey, USA
(2)
London, UK
 

What Is the Difference Between an Object Constructor and an Object Literal ?

Problem

You want to know what the difference is between creating an object using the new operator or an object literal.

Solution

Object literals are usually easer to read. When creating an object literal, you can assign properties at the same time. Using a object constructor can create an object but will require extra lines to define properties.

The Code

var R2D2 = new Object();
    R2D2.class = 'Astromech Droid';
var R2D2 = {
         class:'Astromech Droid';
         manufacturer: 'Industrial Automaton';
};
Listing 9-1.
Objects Can Be Created Using Either the Object Constructor or by Creating an Object Literal

How It Works

Objects can be created both ways. When creating an object literal , you can set all the properties and methods of the object in one statement. This is usually considered easier to read. When creating properties and methods to an object, they are available in every instance of that object.

How Do You Access and Set Properties of an Object?

Problem

You want to know how to access properties of an object.

Solution

Properties can be accessed in two ways—using dot notation or bracket notation .

The Code

var R2D2  = {
};
R2D2['class'] = 'Astromech Droid'
console.log(R2D2['class']);  //returns Astromech Droid
R2D2.manufacturer = 'Industrial Automaton';
console.log(R2D2.manufacturer);  //returns Industrial Automaton
Listing 9-2.
Accessing Properties of an Object Using Dot Notation and Bracket Syntax

How It Works

The term properties are sometimes used when talking about variables assigned to an object and functions assigned to an object. When accessing variables, dot notation is used more often. However you can also use array-like bracket notation. In that case, property names are in quotes. Other languages call this a hash, lookup table, dictionary, or map.
When giving properties names using dot syntax, the same rules apply that you would use for variables. Property names can have numbers, underscores, and dollar signs. However, they cannot start with a number. If you’re using bracket notation, property names must be a string. In this case, the names are not formatted in the same way as if you created properties using dot notation.

What Is the Difference Between Objects and Arrays ?

Problem

You want to know when you should you use an object versus an array.

Solution

Because arrays are indexed, they are iterated in order, whereas with objects, order is not guaranteed. Arrays also have helper methods for adding and removing values. Objects are good at representing groups of data at the cost of order.

The Code

Object.prototype.good = "stuff";
var ship  = {
          type:40,
          name:'tardis',
          color:'blue'
};
for(var prop in ship){
    console.log(prop + ': ' + ship[prop]);
}
var numArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for(var prop in numArray){
    console.log(prop + ': ' + numArray[prop]);
}
for(var i = 0; i <numArray.length; i++){
    console.log(numArray[i]);
}
Listing 9-3.
Some of the Differences Between Objects and Arrays

How It Works

Since almost everything you work with in JavaScript is an object, arrays also inherent properties of objects. Depending on how you loop through the object or array, you access any enumerable property on the object or its prototype. If you’re using a for…in loop, both the array and the object will access the “good” property.
When using a for loop on the array, only the indexed elements are accessed.

Can You Use Variables to Represent Object Properties ?

Problem

You want to know if it’s possible to use variables as properties of an object.

Solution

You can use variables. Objects in JavaScript can use the bracket notation similar to an array when using a variable.

The Code

var ship = {};
var type = 'spaceShip';
ship[type] = 'X-Wing';
console.log(ship[type]); //returns X-Wing
console.log(ship.spaceShip);  //returns X-Wing
console.log(ship.type);  //returns undefined
Listing 9-4.
Using Variables to Access Properties of an Object

How It Works

Objects in JavaScript are sometimes called associated arrays . Instead of having a indexed value, it uses properties. In Listing 9-4, the variable is referencing an object. Next is a variable that is referencing a value. The third line combines the two, and we create a property of the object. Since JavaScript passes objects by reference, you can see from the logs that the property can be used using the square brackets. Since it’s a variable, you do not need to put the property in quotes. However, if you’re accessing the property using dot notation, you would need to access the value and not the variable.

What Does It Mean to Assign Properties of an Object with Metadata?

Problem

You want to create customized properties of an object.

Solution

The defineProperty method of an object will allow you to create custom properties for your object.

The Code

function SuperHeroTeam() {
    this.name = 'The Avengers';
    var _numberOfMembers; // private member
Object.defineProperty(this,"numberOfMemebers",{
    get: function() { return _numberOfMembers; },
    set: function(value) { _numberOfMembers = value; }
});
Object.defineProperty(this,"tagline",{
    value: 'Earth's Mightiest Heroes',
    configurable: false
  });  
}
var team = new SuperHeroTeam();
team.numberOfMembers = 8;
console.log(team.numberOfMembers);
team.tagline = 'The Amazing'; //not editable
console.log(team.tagline);  // returns Earth's Mightiest Heroes
Listing 9-5.
Using the defineProperty Method Inside a Class

How It Works

The defineProperty method allows you to create a custom property and the rules that govern that property. In the first example, we create a getter/setter function called numberOfMembers. You can see in the code the defineProperty method refers to the variable _numberOfMembers. Since functions are objects, this variable is not exposed to the outside. Using the defineProperty method, we can access this variable and give it a value.
We have a similar situation with the second example. The tagline property is set but in this case we set the properties confirmation setting to false. This will make our property read-only. If you try to delete the property, the browser will ignore the request.
There is another option, called enumerable . By default this property is set to false, which means the properties are accessible but you cannot iterate through them. If it’s true, you can iterate through the properties of the object.
In this example, we define two properties, each using the defineProperty method . If you wanted to define them using one method call, use defineProperties.

How Do You Get All the Properties from an Object?

Problem

You want to know both the enumerable and non-enumerable properties of an object.

Solution

The getOwnPropertyNames method of the Object object will return an array of all properties.

The Code

function SuperHeroTeam() {
  this.name = 'The Avengers';
  var _numberOfMembers; // private member
  Object.defineProperty(this,"numberOfMemebers",{
    get: function() { return _numberOfMembers; },
    set: function(value) { _numberOfMembers = value; }
  });
  Object.defineProperty(this,"tagline",{
         value: 'Earth's Mightiest Heroes',
         configurable: false
  });  
}
var team = new SuperHeroTeam();
Object.getOwnPropertyNames(team).forEach(function(val){
          console.log(val); // returns name. numberOfNames, tagline
});
Listing 9-6.
getOwnPropertyNames Returns an Array of All Properties

How It Works

The getOwnPropertyNames method will return an array of both enumerable and non-enumerable properties found in the object. In the case of the enumerable properties, they would return in the same order that they would in a for...in loop.

How Do You Get Just the Enumerable Properties of an Object ?

Problem

You want an array of just the enumerable properties.

Solution

The keys() method will return an array of an object’s enumerable properties.

The Code

var myObj = {a:1, b:2, c:3};
console.log(Object.keys(myObj)); //returns ["a", "b", "c"]
Listing 9-7.
Returning Only the Enumerable Properties of an Object

How It Works

This method will return an array of the object’s enumerable properties, in the same order as if you performed a for..in loop. If you are using ES5 and pass over a primitive (for example, a string), you will receive a type error. If you are using ES6, each letter in the string will return as its index number.

How Do You Know If a Property Is Enumerable?

Problem

You want to check if a property of an object is enumerable.

Solution

The IsEnumerable() method will return true if the property is enumerable.

The Code

var myObj = {a:1, b:2, c:3};
console.log(myObj.propertyIsEnumerable('a')); //returns true
console.log(myObj.propertyIsEnumerable('length')); //returns false
Listing 9-8.
forEach Allows You to Perform a Function on Every Element of an Array, but Passes Undefined If There Is No Value

How It Works

Every object has a propertyIsEnumerable method . It will return true if the property could be enumerated similar to the results of a for..in loop. Properties that are inherited by way of the prototype chain are not checked. If the property is not enumerable, the method will return false.

How Can You Check If an Object Is a Child or Descendant of Another Object ?

Problem

You want to know if the current object has a parent object.

Solution

Object.isPrototypeOf() will return true if one object is the prototype of another object.

The Code

var Person = function(){
    this.firstName =  'Peter',
    this.lastName = 'Parker';
    this.location = 'Queens/New York';
}
var Hero = function(){
    Person.call(this);
    this.heroName = 'Spider-Man';
    this.powers = 'Climb Walls/Shoots Webs';
}
Hero.prototype = Object.create(Person.prototype);
Hero.prototype.constructor = Hero;
var superHero = new Hero();
console.log(Person.prototype.isPrototypeOf(superHero)); //returns true
console.log(superHero instanceof Person); //returns true
Listing 9-9.
Checking If an Object Is the Prototype of Another

How It Works

To understand this method, it helps to think of it in these terms: “Is this object in the prototype chain of another object?”. If that is the case, then the method will return true.
This works in a similar way to instanceOf, although an important difference is that the isPrototypeOf method is part of the Prototype object . In this way, it is available to all objects. Using instanceOf requires two operands, the first being an object, the second being a Constructor function. There it will test if the constructor’s prototype chain exists on the object you are working with.

How Can You Tell If a Property Is on the Current Instance or on the Prototype of an Object?

Problem

JavaScript slows down if it needs to go too far up the prototype chain.

Solution

Use the hasOwnProperty method to check if the property is on the instance or on the prototype chain.

The Code

var Person = function(){
    this.firstName =  'Peter',
    this.lastName = 'Parker';
    this.location = 'Queens/New York';
}
var Hero = function(){
    Person.call(this);
    this.heroName = 'Spider-Man';
    this.powers = 'Climb Walls/Shoots Webs';
}
Hero.prototype = Object.create(Person.prototype);
Hero.prototype.constructor = Hero;
var superHero = new Hero();
console.log(superHero.hasOwnProperty('firstName')); //returns true
console.log(superHero.hasOwnProperty('toString')); //returns false
Listing 9-10.
The firstName Property Is on the Instance, Whereas the toString Property Is Not

How It Works

This method will check if the property is directly on the object. It will not go up the prototype chain. All objects that descend from Object will have access to the hasOwnProperty method . This could also be used inside for..in loops to retrieve only the properties associated with the current object.

How Do You Copy All Enumerable Values from One or More Objects ?

Problem

You need an array of only the elements that meet some criteria.

Solution

Object.assign will copy all enumerable and own properties from one or more objects.

The Code

var person = {firstName: 'Rick Hunter', born:'October 22, 1990'};
var creature = {species: 'Human', gender:'Male', eyes:'Blue', hair:'Black'};
var character = Object.assign(person, creature);
console.log(character);
//returns Object {firstName: "Rick Hunter", born: "October 22, 1990", species: "Human", gender: "Male", eyes: "Blue"...}
Listing 9-11.
The Character Object Has All the Properties of the First Two Objects

How It Works

This method will copy all enumerable and own properties from target objects and assign them to a target object. If a property is non-writeable, the browser will throw a TypeError and not update the object.

What Is the Difference Between Object.create and Using the New Operator ?

Problem

When would you use the new operator over the Object.create method?

Solution

With Object.create you can assign the prototype of the object that you are creating. When using the new operator the methods and properties are not part of the object’s prototype.

The Code

var Human = {
    name: 'Luke Skywalker'
}
var person = Object.create(Human, { droid: {value: 'R2-D2'}});
console.log(person.name);  //returns Luke Skywalker from the prototype
console.log(person.droid); //returns R2-D2
Listing 9-12.
Using the Create Method and Assigning a Prototype Object to It

How It Works

The create method gives you the ability to specify the prototype of the object you are creating. Since a prototype is an object, we pass an object as the first parameter. The second contains all the properties and methods that you want the object to have. If you do not want your object to have a prototype, you can pass null as the first parameter.

Can You Change the Prototype of an Object After the Object Has Been Created?

Problem

You want to change the value of the current prototype object.

Solution

Object.setPrototypeOf will reset the prototype of an object that you created.

The Code

var Human = {
    name: 'Luke Skywalker'
}
var person = Object.create(Human, { droid: {value: 'R2-D2'}});
var person = Object.setPrototypeOf(person, null);
console.log(person.name);  //returns undefined
console.log(person.droid); //returns R2-D2
Listing 9-13.
Updating the Value of the Prototype Object, After Setting It Using Object.create

How It Works

Before using the setPrototypeOf method , you should be aware that updating the prototype is a very slow operation and will affect the performance of every browser. The effect of changing the prototype of an object can have unintended consequences.
If the prototype of the object is extensible, it will be replaced with the object being passed as the second parameter. Otherwise, a TypeError will be thrown. Using this method is part of ECMAScript 6 and considered a better way of updating the prototype object over using the prototype._proto_ property.

How Many Ways Can You Prevent an Object from Being Modified?

Problem

You want to know which methods prevent modification of objects.

Solution

Use the freeze, seal, and preventExtensions methods.

The Code

var robot1 = {
    type: 'Autobot',
    vehicle: 'Truck'
}
var robot2 = {
    type: 'Autobot',
    vehicle: 'Truck'
}
var robot3 = {
    type: 'Autobot',
    vehicle: 'Truck',
    likes: 'Music'
}
var optimusPrime = Object.freeze(robot1);
    optimusPrime.type = 'Decepticon'; //silently fails
    console.log(optimusPrime.type);  //returns Autobot
var hotRod = Object.seal(robot2);
    hotRod.vehicle = 'Car'; //value is updated
    console.log('vehicle = ' + hotRod.vehicle); //returns Car
var jazz = Object.preventExtensions(robot3);
    console.log(jazz.likes); //returns Music
    delete jazz.likes;
    console.log(jazz.likes); //returns undefined
Listing 9-14.
Showing the Difference Between the Freeze, Seal, and preventExtensions Methods

How It Works

The freeze() method prevents properties to be added, modified, or removed. An object in this state is considered immutable.
Seal works similar to the freeze method. Objects by default are extensible , meaning that new properties can be added, modified, and deleted. When sealing an object, new properties cannot be added to the object. Existing properties cannot be modified. One difference with the seal method is that the values of properties can be updated.
Using the preventExtensions method will make an object no longer extensible, meaning that properties that exist at the time the method is being used will still exist, but new ones cannot be created. However, properties of this object can be deleted. Attempting to add new properties will either fail silently or result in a TypeError.

Can You Check If an Object Is Immutable?

Problem

You need to check the mutability of an object.

Solution

The isFrozen, isSealed, and isExtensible methods will check the mutability of an object.

The Code

var optimusPrime = Object.freeze(robot1);
    console.log(Object.isFrozen(optimusPrime));  //returns true
var hotRod = Object.seal(robot2);
    console.log(Object.isSealed(hotRod)); //returns true
var jazz = Object.preventExtensions(robot3);
    console.log(Object.isExtensible(jazz)); //returns false
Listing 9-15.
Testing If Objects Are Immutable

How It Works

Expanding on text examples in the previous sections, when an object is frozen it is not extensible. The isFrozen method will return true if all properties that are not getter or setters are non-writable.
isSealed will return true if properties are not configurable.
The isExtensible method will check if new properties can be added to it.

Can You Tell If Two Values Are the Same?

Problem

You want to compare two different values for equality.

Solution

The Object.is method can be used to check if two values are the same.

The Code

var robot1 = {
    type: 'Autobot',
    vehicle: 'Truck'
}
console.log(Object.is(robot1, robot1)); //returns true
console.log(Object.is(0, false)); //returns false
console.log(Object.is(-0, +0)); //returns false
console.log(Object.is(NaN, NaN)); //returns true
Listing 9-16.
Using the Object.is Method to Compare Two Values

How It Works

When thinking abut this method, it is important to note that is it not the same as using either the equals operator (==) or strict equality (===). The first of these two operators performs coercions if the values are not the same type. The second is considered equal if they are not NaN (not a number) and the same value or if one is +0 and the other -0.
There are some rules to how this method works that separate it from the other ways of testing equality :
  • Both must be undefined
  • Both must be null
  • Both must be either true or false
  • If they are strings, they need the same length and the same characters
  • Both objects must be the same
  • If using numbers, both must be +0, -0, NaN, or have the same value
It is also important to note that browser support is is lacking in Internet Explorer and Safari 7 and 8 (but is supported in Microsoft Edge).

What Is Object Destructuring ?

Problem

You want to extract data from arrays or objects and turn them into distinct values.

Solution

Destructuring objects and arrays, is the ability to bind properties to variables.

The Code

var spaceShip = ['1701-A', '1701-B', '1701-C', '1701-D'];
var [A, B, C, D] = spaceShip;
console.log(D); //returns 1701-D
var timeMachine = {type: 40, color: 'blue', desguise: 'Police Box'};
var {type, color, desguise} = timeMachine;
console.log(desguise);  //returns Police Box
Listing 9-17.
An Example of Destructing an Array and an Object

How It Works

Destructing objects and arrays allows you to assign the values of either variables, then reference those variables directly. In Listing 9-7, the values of the array spaceShip are mapped to an array running A through D. Similarly, the values of the object timeMachine is mapped to an object.
To keep the example simple, the names are the same for the objects and arrays that the values are being mapped to. This does not need to be the case. Once the values have been assigned, they can be used as variables independent of the object or array they originate from.

How Do You Loop Through Objects Using a for…in Loop?

Problem

You want use a for...in loop to iterate through the properties of an object.

Solution

A for...in loop will loop over all enumerable properties. However, if you only want the properties of the object and not its prototype, include the hasOwnProperty method.

The Code

var Hero = function(){
    this.heroName = 'Spider-Man';
    this.powers = 'Climb Walls/Shoots Webs';
}
Hero.prototype.firstName = 'Peter';
Hero.prototype.lastName = 'Parker';
Hero.prototype.location = 'Queens/New York';
var superHero = new Hero();
for(var key in superHero){
    console.log(key + ' = ' + superHero[key]); //returns all properties including what is in the prototype
}
for(var key in superHero){
    if(superHero.hasOwnProperty(key)){
          console.log(key + ' = ' + superHero[key]); //only returns properties directly from the object
        }
}
Listing 9-18.
Looping Through an Object’s Own Properties and Not Properties from Its Prototype

How It Works

By default the for..in loop will display all the properties, including properties included in the prototype chain. If you only are interested in the properties directly associated with the object itself, use the hasOwnProperty method. This will only return objects that are not part of the prototype.

How Do You Loop Through Objects Using a for…of Loop?

Problem

You want to use a for…of loop to iterate through the properties of an object.

Solution

The for...of loop is useful for looping through iterable objects. For example, TypedArrays, arguments, maps, and strings are some of the objects that can be used.

The Code

var myArray = [10, 20, 30];
for (let value of myArray) {
     console.log(value);  //returns 10, 20, 30
}
var myObj = new Object();
    myObj.name = "Rodd";
    myObj.address = "Brooklyn";
for(let value of myObj){
    console.log(value); //returns Uncaught TypeError: myObj[Symbol.iterator] is not a function
}
Listing 9-19.
The for..of Loop Will Loop Through Collections

How It Works

The for...of loop works with iterable objects. This allows JavaScript to define or customize how the values are looped over. Some types like arrays or maps have built-in iterables with a default behavior. Objects however do not have such a feature, resulting in an [Symbol.iterator] error.

How Do You Loop Through Objects Using a do…while loop?

Problem

You want to loop through an object at least one time.

Solution

The do..while loop will loop until a condition returns false. This will execute the statement at least one time.

The Code

var i = 0;
var nameArray = ['Cameron', 'Greyson', 'Vanessa', 'Emily', 'Cate'];
do{
   console.log(nameArray[i]); //returns  Cameron, Greyson Vanessa
   i++;
}while(nameArray[i] != 'Emily');
Listing 9-20.
A do…while loop Will Execute until the Statement Returns a False Value

How It Works

While looping, the condition is evaluated at the end of executing the loop. Because of this, the loop will happen at least one time. If multiple statements need to be evaluated, use a block {} to group statements together.

How Do You Loop Through Objects Using a while Loop ?

Problem

You want to loop through an object as long as the test condition is true.

Solution

The while loop will continue to execute the given statement as long as it evaluates to true.

The Code

var i = 0;
var nameArray = ['Cameron', 'Greyson', 'Vanessa', 'Emily', 'Cate'];
while(i < 2){
     console.log(nameArray[i]); //returns Cameron Greyson
     i++;
}
Listing 9-21.
As Long as the Condition Returns True a While Loop Will Continue to Execute It

How It Works

Similar to the last example, this will loop based on a condition. The exception is that this will loop as long as the condition evaluates to true.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.37.196