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.