Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Building Applications with Spring 5 and Vue.js 2
Building Applications with Spring 5 and Vue.js 2

Building Applications with Spring 5 and Vue.js 2: Build a modern, full-stack web application using Spring Boot and Vuex

eBook
€8.99 €29.99
Paperback
€36.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Building Applications with Spring 5 and Vue.js 2

Modern Web Application Development - This Is a New Era

The diversity of the modern web application development ecosystem is increasing at an astonishing rate. You can see new frameworks and libraries coming out almost every day. People seem to be happy with constantly reinventing the wheel. This could be daunting to new learners as the time it takes to master a new skill makes it sometimes difficult to keep pace with the rate with which technologies are evolving. And this has caused frequent complaints of making web development unnecessarily complicated, as there are many new libraries and frameworks to learn and a large number of new tools to familiarize yourself with. 

The anxiety associated with the feeling that you might not be able to keep up with the mainstream can be released once you have learned how to create a full-stack modern web application and master the skill sets that are required to build such an application. And, with this book, you will learn these skill sets and realize that being a full-stack developer is not only about knowing how to write frontend and backend code. In this book, we will create a real-world, full-stack web application and cover most of the skills that a full-stack developer would require. And once you have finished reading it, you will understand that languages and frameworks are just tools in your toolbox. You can replace them with other languages and frameworks and also build great full-stack applications.

To start our journey, we will begin with the basics. Once you have those basics imprinted in your mind, you can learn the frameworks more efficiently. In this chapter, we will cover the following topics:

  • An introduction to the full-stack web application we will build in this book
  • Learning JavaScript from a Java developer's viewpoint
  • Learning the features of ECMAScript 2015 that we will use in this book

Introduction

If you're creating a résumé page for your personal website, it will most likely be sufficient to write it in vanilla JavaScript, HTML 5, and some creative CSS style sheets that make it look special and unique. And if you're creating the jobs page of your company's official website, doing it barehanded might work. But if you use a number of frameworks to style the page and to process logic and animations, you will find yourself in a much better position that you can still go home from work earlier than usual and enjoy a cup of coffee with friends at the weekend. And if you're building something like Monster (https://www.monster.com/) I hope that you are not just carrying those favorite frameworks with you to the battlefield, and if you go barehanded, you wouldn't even make it there. With the level of complexity of such an application and the fact that you will need to keep improving or changing features because of the neverending stop-change requirements, you need to bring the tools for modern web application development with you.

Sometimes, people use the term vanilla JavaScript to refer to using plain JavaScript without any additional libraries, such as jQuery, Lodash, and many more. That means that you write your code with only the APIs that the JavaScript language itself provides.

In this book, we will create a modern web application called TaskAgile, which is a Trello-like application for task management. Let's first get an overview of the technologies that we will use to build it.

For the frontend, we will use Vue.js 2 as our frontend application framework, Bootstrap 4 as the UI framework, and we will write our frontend in ES6, also known as ECMAScript 2015, or ES 2015, and then use Babel to compile it into ES5 code. We will use ESLint to check our JS code to make sure it follows all the rules we defined and use Flow (https://flow.org) for static type checking. We will use Jest to write our frontend unit testing's and use Nightwatch.js to run our end-to-end test cases. We will use webpack 4 to bundle all the dependencies and use npm to take care of the package management.

For the backend, we will use Spring Boot 2 to create a Spring 5 application. And we will use Hibernate 5 as our object-relational mapping (ORM) framework, and MySQL as our database. We will use Spring Security for authentication and authorization, and we will implement a real-time-update feature with Spring WebSocket. We will use Spring AMPQ for asynchronously processing background tasks and Spring Session for server-side session management.

Now, before we introduce Vue.js 2 and Spring 5, for readers who are not familiar with JavaScript, let's learn the basics of it, starting with the part that Java developers would easily get confused with. 

JavaScript from a Java developer's viewpoint

For readers who are new to JavaScript but who are familiar with the Java language, here are some differences between the two languages that may confuse you. And even though this section is written from a Java developer's perspective, if you're new to JavaScript, you will also find it informative.

Functions and methods

A function in JavaScript is quite different from a method in Java because it is actually an object created by the Function constructor, which is a built-in object of the language. Yes, that's right. Function itself is an object too. What is a method in JavaScript, then? When a function is a property of an object, it is a method. So, in JavaScript, a method is a function, but not all functions are methods.

Since a function is an object, it can also have properties and methods. To establish whether an object is a function or not, you can use instanceofas follows:

var workout = function () {};
console.log(workout instanceof Function); // true

What is the difference between a function and other objects in JavaScript, apart from the fact that it is created by the Function constructor? First of all, a function is callable, while other objects are not. Another difference is that a function has a prototype property while other objects don't. We will talk about prototype later.

In JavaScript, you can use a function to create objects with new. In a case such as this, that function serves as a constructor. As a convention, when a function serves as a constructor, it should be capitalized. The following is a simple example of using a function as a User constructor. We will build the User constructor containing more details later:

function User () {
}
var user = new User();

Before we move on, let's see the different ways to create a function in JavaScript. Function declarations and function expressions are the most common ways to create functions. Other than that, you can use new Function() to create a function. However, this is not recommended due to its poor performance as well as its readability. The User function in the preceding code snippet is a function declaration. And workout is a function expression. The way that a function is created and invoked will affect the execution context that its function body will point to. We will talk about it later.

Objects and classes

In Java, you create a class to represent a concept, for example, a User class. The User class has a constructor, some fields, and methods. And you use its constructor to instantiate a User object. And every object in Java is an instance of the associated class that provides code sharing among its instances. You can extend the User class to create, for example, a TeamMember class.

In JavaScript, there are several ways to create an object:

  • The Object() constructor method
  • The object literal method
  • The constructor function method
  • The Object.create() method
  • The creator function method
  • The ES6 class method

Let's look at each method one at a time.

The Object constructor method looks like this:

// Call the Object constructor with new
var user = new Object();
user.name = 'Sunny';
user.interests = ['Traveling', 'Swimming'];
user.greeting = function () {
console.log('Hi, I\'m ' + this.name + '.');
};
user.greeting(); // Hi, I'm Sunny.

The Object constructor creates an object wrapper. This is not a recommended approach, even though it is valid in JavaScript. In practice, it is better to use an object literal instead, which makes the code compact.

The object literal method looks like this:

// Create a user with object literal
var user = {
name: 'Sunny',
interests: ['Traveling', 'Swimming'],
greeting: function () {
console.log('Hi, I\'m ' + this.name + '.');
}
}
user.greeting(); // Hi, I'm Sunny.

The object literal is a compact syntax to create an object in JavaScript and it is the recommended way of creating an object over new Object(). Starting from ES5, object literals also support getter and setter accessors, as can be seen here:

var user = {
get role() {
return 'Engineer';
}
}
user.role; // Engineer

And if you try to assign a value to role, it will stay unchanged because there is no setter accessor defined for the role property.

The constructor function method looks like this:

// Create a constructor function
function User (name, interests) {
this.name = name;
this.interests = interests;
this.greeting = function () {
console.log('Hi, I\'m ' + this.name + '.');
}
}
// Call the constructor with new to create a user object
var user = new User('Sunny', ['Traveling', 'Swimming']);
user.greeting(); // Hi, I'm Sunny.

This syntax is very close to the one in Java. JavaScript is very tolerant, and you can omit the parenthesis when calling the constructor. However, this will not pass any arguments to the constructor, as can be seen here:

var user = new User;
console.log(user.name); // undefined

And again, even though this is valid in JavaScript, it is not recommended to omit the parenthesis.

The Object.create() method looks like this:

// Use Object.create() method with the prototype of
// User constructor function created above
var user = Object.create(User.prototype, {
name: { value: 'Sunny' },
interests: { value: ['Traveling', 'Swimming']}
});
user.greeting(); // Uncaught TypeError: user.greeting() is not a //function

The reason greeting() is not a function of the user object here is that the Object.create() method creates a new object with the constructor's prototype object. And the greeting function is not defined in User.prototype, or passed in the second argument of Object.create(). To make the user be able to greet, we can either pass the greeting function in the second argument, or we can add it to the User constructor's prototype object. The difference is that the first approach only adds the greeting function to the current user object. If you created another user without passing in the greeting function, that user won't have greeting function. On the other hand, adding the function to the prototype object will add the greeting function to all the objects created by that constructor. Let's add it to the User prototype object:

// Add greeting to prototype object
User.prototype.greeting = function () {
console.log('Hi, I\'m ' + this.name + '.');
}
user.greeting(); // Hi, I'm Sunny.

Actually, using a prototype is how a superclass provides methods for subclasses to inherit in JavaScript. We will talk about that in detail later.

The creator function method looks like this:

// Use a creator function with an object as its return value
function createUser (name, interests) {
var user = {};
user.name = name;
user.interests = interests;
user.greeting = function () {
console.log('Hi, I\'m ' + this.name + '.');
};
return user;
}
// Call the creator function with parameters
var user = createUser('Sunny', ['Traveling', 'Swimming']);
user.greeting(); // Hi, I'm Sunny.

The creator function here is a factory method, similar to the static factory method that used to instantiate an object in Java. And it is merely a pattern because underneath it wraps the object creation details inside of the creator function.

The ES6 class method looks like this:

// Create User class
class User {
// Equivalent to User constructor function
constructor (name, interests) {
this.name = name;
this.interests = interests;
}
// Equivalent to User.prototype.greeting
greeting () {
console.log('Hi, I\'m ' + this.name + '.')
}
}
let user = new User('Sunny', ['Traveling', 'Swimming']);
user.greeting(); // Hi, I'm Sunny.

This is very close to the syntax in Java. Instead of using the class declaration, you can also use the class expression to create the class, as follows:

// Use class expression
let User = class {
constructor (name, interests) {
this.name = name;
this.interests = interests;
}
greeting () {
console.log('Hi, I\'m ' + this.name + '.')
}
}

Even though it uses the same keyword, class, class in JavaScript is quite different from the class in Java. For example, there is no static class and no private class in JavaScript. We will talk more about class in the ES6 section.

Objects, properties, and property attributes

In Java, once an object is created, there is (almost) no way to modify its methods during runtime. Java is not a dynamic language. In JavaScript, things are quite different. You can create an object and modify it easily during runtime, such as adding new properties and replacing a method. That's what a dynamic language can do. Actually, that is not the special part. The special part is that Object is a language type in JavaScript, like other language types that JavaScript has, which includes Undefined, Null, Boolean, String, Symbol, and Number. Any value in JavaScript is a value of those types.

The undefined type has a single value, undefined. The null type has a single value, null. A Boolean has two values: true and false.

In Java, an object has fields and methods. In JavaScript, an object is logically a collection of properties. A property has a name of the String type and a list of attributes. Attributes, in JavaScript, are used to define and explain the state of a property. There are two types of properties—data properties and access properties.

A data property has four attributes:

  • value, which can be of any JavaScript language type
  • writable, which defines whether a data property can be changed or not
  • enumerable, which defines whether a property can be enumerated by using a for-in statement
  • configurable, which defines whether a property can be deleted, changed to be an access property, changed to be not writable, or whether its enumerable attribute can be modified

An access property also has four attributes:

  • get accessor, which can be a Function object or undefined
  • set accessor, which can be a Function object or undefined
  • enumerable, which defines whether a property can be enumerated by using a for-in statement
  • configurable, which defines whether a property can be deleted, be changed to be a data property, or whether its other attributes can be modified.

To access a property of an object, you can use dot notation or bracket notation. The dot notation acts the same as how it does in Java. The bracket notation, on the other hand, is quite interesting. In JavaScript, property names must be strings. If you try to use a non-string object as a property name with bracket notation, the object will be casted into a string via its toString() method, as we can see here:

var obj = {};
obj['100'] = 'one hundred';
// Number 100 will be casted to '100'
console.log(obj[100]); // 'one hundred'
// Both foo and bar will be casted to string '[object Object]'
var foo = {prop: 'f'}, bar = {prop: 'b'};
obj[foo] = 'Foo'
console.log(obj[bar]) // 'Foo'

In a nutshell, here is how an object appears, logically:

Figure 1.1: Object, properties, and property attributes

In JavaScript, you can use Object.defineProperty or Object.defineProperties to modify the properties of an object. Here is how it works:

1.  function User (name, department) {
2. var _department = department;
3. var _name = name;
4. Object.defineProperty(this, 'name', {
5. value: _name,
6. writable: true,
7. enumerable: true,
8. configurable: false
9. });
10. Object.defineProperty(this, 'department', {
11. get: function () {
12. console.log('Retrieving department');
13. return _department;
14. },
15. set: function (newValue) {
16. console.log('Updating department value to "' + newValue + '"');
17. _department = newValue;
18. },
19. enumerable: true,
20. configurable: true
21. });
24. Object.defineProperty(this, 'greeting', {
25. value: function () {
26. console.log('Hi, I\'m ' + _name + '.');
27. },
28. enumerable: false,
29. configurable: false
30. });
31. }

As you can see from lines 4 to 9, we use Object.defineProperty to define name as a data property, and its actual data is stored in the internal property _name. In lines 10 to 21, we define department as an access property that has a get accessor and set accessor, and the actual value is kept in _department. In lines 24 to 30, we define greeting property as a data property and its value is a Function object:

32. var user = new User('Sunny', 'Engineering');      
33. console.log(user.department);
34. user.department = 'Marketing';
35. user.greeting();
36. Object.defineProperty(user, 'name', {
37. enumerable: false
38. });
39. delete user.name;
40. delete user.department;
41. for (var prop in user) {
42. console.log(prop);
43. }

In line 32, we create a user object using the User constructor function. In line 33, we access the department property. Since it is a get accessor, the getter function will be invoked and the message Retrieving department will show up in the console before the actual department value. In line 34, we assign a new value to the department property. Since we have defined the set accessor, the setter function will be invoked. In line 35, since the greeting property of user object is defined as a function, we will need to invoke it. In lines 36 to 38, we try to redefine the name property. However, since it is not configurable, JavaScript will throw an error with this. The same is true with regard to line 39, where we try to delete this property. The deletion of department property in line 40 will work since it is configurable. In lines 41 to 43, the only property that will show up in the console is the name property, because the department has been deleted and the greeting property is not enumerable.

Prototype and inheritance

As has been briefly mentioned previously, inheritance in JavaScript is archived by using prototypes of constructor functions. In JavaScript, a prototype is an object that provides shared properties for other objects. And only a function object has a prototype because only a function object is callable and can create other objects. In ES6, arrow functions don't have prototypes. We will discuss that later.

You can think of a function as a factory and its prototype is the specification of the products that the factory manufactures. Every time you call a function with the new keyword, you place an order for its product. And the factory will produce it according to how it is specified in the prototype.

Now, let's see how inheritance works in code. We will create another constructor function, called TeamMemberand it will inherit properties from User and also override the greeting() method and provide a new method called work(). Later, we will add eat() method to User and move() to Object.

Here is how it is implemented in ES5:

1. function User (name, interests) {
2. this.name = name;
3. this.interests = interests;
4. }
5. User.prototype.greeting = function () {
6. console.log('Hi, I\'m ' + this.name + '.');
7. }

In lines 1 to 4, we create a User constructor function. And what it really does is create a function object using the Function constructor. In JavaScript, you can check who created an object by using its constructor property, which references back to its creator, as follows:

console.log(User.constructor === Function);  // true

And once the User constructor function is created, it has a prototype object. And a User prototype object itself is created by the User constructor function, as you can see in the following:

console.log(User.prototype.constructor === User); // true 

And in JavaScript, after you create a user object using the User constructor function, that object will have a __proto__ property that references the User prototype object. You can see the link like this:

var user = new User();
console.log(user.__proto__ === User.prototype);
// true

This __proto__ reference serves as a link in the prototype chain. You will see what that means visually later.

Now back to the code. In lines 5 to 7, we create a greeting property on the User prototype. This will create a method that can be inherited by User subclasses. And, as we mentioned earlier, if you define the greeting method inside the User constructor function, subclasses won't see this greeting method. We will see the reason for this shortly:

8.  function TeamMember (name, interests, tasks) {
9. User.call(this, name, interests);
10. this.tasks = tasks;
11. }
12. TeamMember.prototype = Object.create(User.prototype);
13. TeamMember.prototype.greeting = function () {
14. console.log('I\'m ' + this.name + '. Welcome to the team!');
15. };
16. TeamMember.prototype.work = function () {
17. console.log('I\'m working on ' + this.tasks.length + ' tasks');
18. };

In lines 8 to 13, we create a TeamMember constructor function, and inside it, we invoke the User constructor function's call() method, which is inherited from the Function object to chain constructors, which is similar to invoking super() in a constructor of a Java class. One difference is that the call() method's first argument must be an object, which serves as the execution context. In our example, we use this as the execution context. Inside the call() method, the name and interests properties are initialized. And then, we add an additional property, tasksto TeamMember.

In line 12, we use Object.create() to create a TeamMember prototype object using the User prototype object. In this way, objects created by the TeamMember constructor function will have the properties of the User prototype object and each team member object will have a __proto__ property that links to this TeamMember prototype.

In lines 13 to 15, we override the original greeting() method of the User prototype so that objects created by the TeamMember constructor function will have different behavior. This will not affect the User prototype object since they are essentially two different objects, even though these two prototype objects have the same constructor, as you can see in the following:

console.log(User.prototype === TeamMember.prototype);  // false
console.log(User.prototype.constructor === TeamMember.prototype.constructor); // true

In lines 16 to 18, we add a new method, work()to the TeamMember prototype object. In this way, objects created by the TeamMember constructor function will have this additional behavior:

19. var member = new TeamMember('Sunny', ['Traveling'],
20. ['Buy three tickets','Book a hotel']);
21. member.greeting(); // I'm Sunny. Welcome to the team!
22. member.work(); // I'm working on 2 tasks
23
24. console.log(member instanceof TeamMember); // true
25. console.log(member instanceof User); // true
26. console.log(member instanceof Object); // true
27
28. User.prototype.eat = function () {
29. console.log('What will I have for lunch?');
30. };
31. member.eat(); // What will I have for lunch?
32
33. // Add a method to the top
34. Object.prototype.move = function () {
35. console.log('Every object can move now');
36. };
37. member.move(); // Every object can move now
38. var alien = {};
39. alien.move(); // Every object can move now
40. User.move(); // Even the constructor function

In line 19, we create a member object using the TeamMember constructor function. Line 21 shows that the member object can greet in a different way to objects created by the User constructor function. And line 22 shows that the member object can work.

Lines 24 to 26 show that the member object is an instance of all its superclasses.

In lines 28 to 30, we add the eat() method to the User prototype, and even though the member object is created before this, as you can see from line 31, it also inherits that method.

In line 34, we add the move() method to the Object prototype, which might turn out to be a really bad idea since, as you can see in lines 37 to 40, every object can move now, even those constructor function objects.

We just create an inheritance chain starting from Object | User | TeamMember. The prototype link is the key to this chain. Here is how it appears:

Figure 1.2: Prototype-based inheritance

On the left-hand side are the constructor functions, and on the right-hand side are their corresponding prototypes. The bottom is the member object. As you can see, the member object's __proto__ property references the prototype object of TeamMember. And the __proto__ property of the TeamMember prototype object itself references the prototype object of User. And the __proto__ property of the User prototype object references the top level, which is the prototype object of ObjectTo verify the link, you can do something like this:

console.log(member.__proto__ === TeamMember.prototype);         // true
console.log(TeamMember.prototype.__proto__ === User.prototype); // true
console.log(User.prototype.__proto__ === Object.prototype); // true

So, be really careful with the __proto__ property. If you, let's say, accidentally change this property to something else, the inheritance will break:

User.prototype.__proto__ = null;
member.move(); // Uncaught TypeError: member.move is not a function
console.log(member instanceof Object); // false (Oops!)

It is recommended to use Object.prototype.isPrototypeof() to check the prototype chain:

TeamMember.prototype.isPrototypeOf(member);   // true

With the inheritance relationship map showing in the preceding diagram, you can easily see how JavaScript resolves a property through the prototype chain. For example, when you access a member object's name property, JavaScript finds that it is on the object itself and will not go up the chain. And when you access the move() method, JavaScript will go up the chain and check whether the TeamMember prototype has it and, since it doesn't, JavaScript will keep going up until it finds the method in the Object prototype. You can use an object's hasOwnProperty() method to check whether that object has a property as its own instead of inherited through the prototype chain:

member.hasOwnProperty('name');   // true
member.hasOwnProperty('move'); // false

Scope and closure

Scope is about the accessibility of variables. In Java, basically, a set of curly brackets {} defines a scope, including class-level scope, method-level scope, and block-level scope. 

Let's take a look at the following example in Java:

1.  public class User { 
2. private String name;
3. private List<String> interests;
4.
5. public User (String name, List<String> interests) {
6. this.name = name;
7. this.interests = interests;
8. }
9.
10. // Check if a user is interested in something
11. public boolean isInterestedIn(String something) {
12. boolean interested = false;
13. for (int i = 0; i < interests.size(); i++) {
14. if (interests.get(i).equals(something)) {
15. interested = true;
16. break;
17. }
18. }
19. return interested;
20. }
21. }

The name and interests properties are in the class-level scope and they are accessible anywhere within the class. The interested variable, defined in line 12, is in method-level scope, and it is only accessible within that method. The i variable, in line 13, is defined within the for loop and it is block-level scope only accessible within the for loop block. In Java, the scope of the variables is static and can be determined by the compiler.

In JavaScript, the scope of the variables is much more flexible. There is global scope and function scope, and block scope with the let and const keywords, which were introduced in ES6, which we will talk about later.

Let's look at the following JavaScript example:

1.  function bookHotel (city) {
2. var availableHotel = 'None';
3. for (var i=0; i<hotels.length; i++) {
4. var hotel = hotels[i];
5. if (hotel.city === city && hotel.hasRoom) {
6. availableHotel = hotel.name;
7. break;
8. }
9. }
10. // i and hotel still accessible here
11. console.log('Checked ' + (i+1) + ' hotels');// Checked 2 hotels
12. console.log('Last checked ' + hotel.name); // Last checked Hotel B
13. {
14. function placeOrder() {
15. var totalAmount = 200;
16. console.log('Order placed to ' + availableHotel);
17. }
18. }
19. placeOrder();
20. // Not accessible
21. // console.log(totalAmount);
22. return availableHotel;
23. }
24. var hotels = [{name: 'Hotel A', hasRoom: false, city: 'Sanya'},
{name: 'Hotel B', hasRoom: true, city: 'Sanya'}];
25. console.log(bookHotel('Sanya')); // Hotel B
26. // Not accessible
27. // console.log(availableHotel);

The hotels variable declared in line 24, is in global scope and is accessible anywhere, such as inside the bookHotel() function, even though the variable is defined after the function. 

The availableHotel variable declared in line 2 is in the scope of the bookHotel() function. It is a local variable and is not accessible outside of the function, as you can see from line 27. Inside its enclosing function, the availableHotel variable is accessible anywhere, even the nested placeOrder() function, as you can see in line 16. This is called closure. A closure is formed when a function is nested inside another function. And no matter how deeply you have nested a function, it will still have access to its parent function's scope, and all the way to the top scope, which is global scope. The totalAmount variable, defined in line 15, is a local variable of the placeOrder() function.

And in lines 3 and 4, we defined the i and hotel variables with the var keyword. Even though it is in a for loop block, it is still accessible outside the block, as shown in lines 11 and 12. In ES6, you can use the let keyword to define i and hotel, which will put these two variables in for loop block scope. We will talk more about this later.

The this keyword

In Java, this always refers to the current object. It is solid. In JavaScript, this behaves differently. In short, this refers to the current execution context, which is an object. And the way that JavaScript runtime determines the current execution context is much more complex than in Java.

In JavaScript, there is an execution context stack, logically formed from active execution contexts. When control is transferred from one executable code to another, control enters the new executable code's execution context, which becomes the current execution context, or what is referred to as the running execution context. At the bottom of the stack is the global context, where everything begins, just like the main method in Java. The current execution context is always at the top of the stack.

What is the executable code? There are three types in JavaScript:

  • Global code, which is the code that runs from the place where a JavaScript program starts. In a browser, it is where window lives. And when you open a browser console and type in var user = new User(), you are writing global code.
  • Eval code, which is a string value passed in as the argument of the built-in eval() function (do not use the eval() function unless you really know what you're doing).
  • Function code, which is the code parsed as the body of a function. However, it doesn't mean all the code written inside a function is function code.

Now, to understand this better, let's look at the following example:

1.  function User (name) {
2. console.log('I\'m in "' + this.constructor.name + '" context.');
3. this.name = name;
4. this.speak = function () {
5. console.log(this.name + ' is speaking from "' +
6. this.constructor.name + '" context.');
7. var drink = function () {
8. console.log('Drinking in "' + this.constructor.name + '"');
9. }
10. drink();
11. };
12. function ask() {
13. console.log('Asking from "' +
14. this.constructor.name + '" context.');
15. console.log('Who am I? "' + this.name + '"');
16. }
17. ask();
18. }
19. var name = 'Unknown';
20. var user = new User('Ted');
21. user.speak();
Since an execution context is, in fact, an object, here we use its .constructor.name to see what the context is. And if you run the preceding code in the node command line, it will be Object instead of Window.

If you run the code from Chrome console, the output will be the following:

// I'm in "User" context.
// Asking from "Window" context.
// Who am I? "Unknown"
// Ted is speaking from "User" context.
// Drinking in "Window"

First, let's see which part is global code and which part is function code. The User function declaration, and lines 19 to 21, are global code. Lines 2 to 17 are the function code of the User function. Well, not exactly. Lines 5 to 10, except line 8, are the function code of the speak() method. Line 8 is the function code of the drink() function. Lines 13 and 14 are the function code of the ask() function.

Before we review the output, let's revisit the two commonly used ways of creating a function—function declarations and function expressions. When the JavaScript engine sees a function declaration, it will create a function object that is visible in the scope in which the function is declared. For example, line 1 declares the User function, which is visible in global scope. Line 12 declares the ask() function, which is visible inside the scope of the User function. And line 4 is a function expression that creates the speak() method. On the other hand, in line 7, we use a function expression to create a drink variable. It is different from the speak() method created in line 4. Even though it is also a function expression, the drink variable is not a property of an object. It is simply visible inside the speak() method.

In JavaScript, scope and execution context are two different concepts. Scope is about accessibility, while the execution context is about the ownership of running an executable code. The speak() method and the ask() function are in the same scope, but they have different execution contexts. When the ask() function is executed, as you can see from the output, it has global context and the name property resolves to the value Unknown, which is declared in global scope. And when the speak() method is executed, it has the user context. As you can see from the output, its access to the name property resolves to Ted. This can be quite confusing to Java developers. So what happened behind the scenes?

Let's review the preceding example from the JavaScript engine's view. When the JavaScript engine executes line 20, it creates a user object by calling the User constructor function. And it will go into the function body to instantiate the object. When the control flows from the global code to the function code, the execution context is changed to the user object. And that's why you see I'm in "User" context. in the output. And during the instantiation, JavaScript engine will not execute the code inside the speak() method because there is no invoking yet. It executes the ask() function when it reaches line 17. At that time, the control flows from the function code of the User constructor function to the ask() function. Because the ask() function isn't a property of an object, nor it is invoked by the Function.call() method, which we will talk about later, the global context becomes the execution context. And that's why you see Asking from "Window" context. and Where am I? "Unknown" in the output. After the instantiation of the user object, the JavaScript engine goes back to execute line 21 and invokes the speak() method on the user object. Now, the control flows into the speak() method and the user object becomes the execution context. And that's why you see Ted is speaking from "User" context. in the output. When the engine executes the drink() function, it resolves back to the global context as the execution context. And that is why you see Drinking in "Window" context. in the output.

As mentioned earlier, the execution context is affected by the way a function is created as well as by how it is invoked. What does that mean? Let's change line 16 from ask() to ask.call(this). And if you run the preceding example again from Chrome's console, you can see the following output:

...
Asking from "User" context.
Who am I? "Ted"
...

And if you type in user.speak.apply({name: 'Jack'}) into the console, you will see something interesting, like this:

Jack is speaking from "Object" context.
Drinking in "Window" context.

Or, if you change line 17 to ask.bind(this)(), you can see the answer to the question "Who am I?" is also "Ted" now.

So, what are these call(), apply(), and bind() methods? It seems that there are no definitions of them in the preceding example. As you might remember, every function is an object created by the Function object. After typing in the following code into the console, you can see that the speak() function inherits the properties from Function prototype, including the call(), apply(), and bind() methods:

console.log(Function.prototype.isPrototypeOf(user.speak)); // true
user.speak.hasOwnProperty('apply'); // false
user.speak.__proto__.hasOwnProperty('apply'); // true

The call() method and the apply() method are similar. The difference between these two methods is that the call() method accepts a list of arguments, while the apply() method accepts an array of arguments. Both methods take the first argument as the execution context of the function code. For example, in user.speak.apply({name: 'Jack'}), the {name: 'Jack'} object will be the execution context of the speak() method of user. You can think of the call() and apply() methods as a way of switching execution context.

And the bind() method acts differently from the other two. What the bind() method does is create a new function that will be bound to the first argument that is passed in as the new function’s execution context. The new function will never change its execution context even if you use call() or apply() to switch execution context. So, what ask.bind(this)() does is create a function and then execute it immediately. Besides executing it immediately, you can assign the new function to a variable or as a method of an object.

To wrap up, there are four ways to invoke a function:

  • Constructor function invoking: new User()
  • Direct function invoking: ask()
  • Method invoking: user.speak()
  • Switching context invoking: ask.call(this) or ask.apply(this)

When we are talking about constructor function invoking, the presence of this inside the function body, except those instances that are wrapped by functions of the other three types of invoking, refers to the object that the constructor creates.

When we are talking about direct function invoking, the presence of this inside the function body, except those instances that are wrapped by functions of the other three types of invoking, refers to the global context.

When we are talking about method invoking, the presence of this inside the function body, except those instances that are wrapped by functions of the other three types of invoking, refers to the object that the method belongs to.

When we are talking about switching context invoking, the presence of this inside the function body, except those instances that are wrapped by functions of the other three types of invoking, refers to the object that passed in as the first argument of the call() method.

Hoisting

This is another thing that Java developers usually easily get confused. Hoisting is a metaphor for the way that JavaScript interpreters will lift function declarations and variable declarations to the top of their containing scope. So, In JavaScript, you can see something that is obviously wrong and will definitely break the compilation if you write that in Java, but it is totally valid in JavaScript.

Let’s see an example:

1. travel = 'No plan';
2. var travel;
3. console.log(travel); // Is the output: undefined?
4.
5. function travel() {
6. console.log('Traveling');
7. }
8. travel(); // Is the output: Traveling?

What will the output be when the JavaScript engine executes line 3 and 8? It is not undefined, and not Traveling. Line 3 is "No plan" and line 8 is "Uncaught TypeError".

Here is what the JavaScript interpreter sees when it processes the preceding code:

1.  // Function declaration moved to the top of the scope
2. function travel() {
3. console.log('Traveling');
4. }
5. // Variable declaration moved under function declaration
6. var travel;
7. travel = 'No plan';
8.
9. console.log(travel); // No plan
10. travel(); // Uncaught TypeError: travel is not a function

JavaScript interpreter moves the function declarations up to the top, followed by variables declarations. Function expressions, for example, var travel = function(){}, are not lifted to the top as function declarations because they are also variable declarations.

Let's see another example:

1.  function workout() { 
2. goToGym(); // What will the output be?
3. var goToGym = function () {
4. console.log('Workout in Gym A');
5. }
6. return;
7. function goToGym() {
8. console.log('Workout in Gym B');
9. }
10. }
11. workout();

What will the output be when line 2 is executed? It is "Workout in Gym B.". And here is what the interpreter sees when it processes the code:

1.  function workout() {
2. function goToGym() {
3. console.log('Workout in Gym B');
4. }
5. var goToGym;
6. goToGym();
7. goToGym = function () {
8. console.log('Workout in Gym A');
9. }
10. return;
11. }
12. workout();

The interpreter moves the function declaration to the top of the scope and then the variable declaration, but not the assignment. So when goToGym() is executed, the assignment expression to the new function hasn't happened yet.

To wrap up, before executing, JavaScript interpreters will move the function declarations, and then variable declarations, without assignment expressions, up to the top of the containing scope. And it is valid to put function declarations after the return statement.

ES6 basics

ES6 (short for ECMAScript 2015), is the sixth version of ECMAScript, which is a general-purpose, cross-platform, and vendor-neutral programming language. ECMAScript is defined in ECMA Standard (ECMA-262) by Ecma International. Most of the time, ECMAScript is more commonly known by the name JavaScript.

Understanding ES6 is the key to writing web applications using modern JavaScript. Owing to the scope of this book, we will only cover the basics of new features introduced in ES6 here as you will see them in the rest of the book.

Block scoping, let, and const

As mentioned earlier, in ES6, you can use let to define variables or use const to define constants, and they will have block-level scope. And in the same scope, you can not redefine a variable using let. Also, you cannot access a variable or a constant that is defined with let or const before its declaration, since there is no variable hoisting with let or const.

Let's see the following workout example:

1.  function workout() {
2. let gym = 'Gym A';
3.
4. const gymStatuses = {'Gym A': 'open', 'Gym B': 'closed'};
5. for (let gym in gymStatuses) {
6. console.log(gym + ' is ' + gymStatuses[gym]);
7. }
8.
9. {
10. const gym = 'Gym B';
11. console.log('Workout in ' + gym);
12. // The following will throw TypeError
13. // gym = 'Gym C';
14. }
15.
16. console.log('Workout in ' + gym);
17.
18. {
19. function gym () {
20. console.log('Workout in a separate gym');
21. }
22. gym();
23. }
24.
25. if (gymStatuses[gym] == 'open') {
26. let exercises = ['Treadmill', 'Pushup', 'Spinning'];
27. }
28. // exercises are no longer accessible here
29. // console.log(exercises);
30.
31. try {
32. let gym = 'Gym C';
33. console.log('Workout in ' + gym);
34. throw new Error('Gym is closed');
35. } catch (err) {
36. console.log(err);
37. let gym = 'Gym D';
38. console.log('Workout in ' + gym);
39. }
40. }
41. workout();

In line 2, we declare the gym variable, and it is visible in the workout() function body. In line 5, we declare the gym variable within the for loop block. It shadows the gym variable declared in line 2 and is only accessible within that for loop block.

In lines 9 to 14, we declare a new scope using a block statement. The gym constant declared in line 10 is only accessible within that scope. And as you can see in line 13, assigning a value to a constant will cause TypeError.

In line 16, the gym variable is back to the one declared in line 2. In lines 18 to 23, we declare the gym function and it is only accessible within that block.

In line 26, we define the exercises variable within the if block. And as you can see from line 29, it is no longer accessible outside the if block.

In lines 31 to 39, we declare a try-catch block. As you can see in lines 32 and 37, the try block and catch block are in different scopes.

To wrap up, using let and const, we can archive block-level scope with for loop blocks, if blocks, try-catch blocks, and block statements, as well as switch blocks.

Classes

ES2015 introduces classes, which is primarily a syntactical sugar over prototype-based inheritance. With the class syntax, you can create constructors, extends from a superclass, and create static methods, as well as getters and setters.

Let's see the following example that uses the class syntax to implement User, and TeamMember:

1.  class User {
2. constructor(name, interests) {
3. this.name = name;
4. this.interests = interests;
5. }
6. greeting () {
7. console.log('Hi, I\'m ' + this.name + '.');
8. }
9. get interestsCount () {
10. return this.interests ? this.interests.length : 0;
11. }
12. }

In lines 1 to 12, we define class Userwhich accepts two arguments via its constructor. It has a greeting() method and an interestsCount getter:

13. class TeamMember extends User {
14. constructor(name, interests) {
15. super(name, interests);
16. this._tasks = [];
17. this._welcomeText = 'Welcome to the team!';
18. }
19. greeting () {
20. console.log('I\' m ' + this.name + '. ' + this._welcomeText);
21. }
22. work () {
23. console.log('I\' m working on ' + this._tasks.length + '
tasks.')
24. }
25. set tasks (tasks) {
26. let acceptedTasks = [];
27. if (tasks.length > TeamMember.maxTasksCapacity()) {
28. acceptedTasks = tasks.slice(0,
TeamMember.maxTasksCapacity());
29. console.log('It\'s over max capacity. Can only take two.');
30. } else {
31. acceptedTasks = tasks;
32. }
33. this._tasks = this._tasks.concat(acceptedTasks);
34. }
35. static maxTasksCapacity () {
36. return 2;
37. }
38. }

In lines 13 to 38, we create a TeamMember class to extend from User. In its constructor, it calls the constructor of the User with super to instantiate the properties of name and interests. We also define two additional properties, _tasks and _welcomeText. The preceding underscore suggests that they are regarded as private properties and should not be changed directly from outside. However, nothing is private in JavaScript. You can still access these properties, for example, member._tasks, and member._welcomeText.

We override the greeting() method of user in line 20 and add a new work() method in line 22. In lines 25 to 34, we define a setter tasks, inside which we access the maxTasksCapacity() static method of TeamMember:

39. let member = new TeamMember('Sunny', ['Traveling']);
40. member.greeting(); // I' m Sunny. Welcome to the team!
41. member.tasks = ['Buy three tickets', 'Book a hotel', 'Rent a car'];
// It's over max capacity. Can only take two.
42. member.work(); // I' m working on 2 tasks.
43. console.log(member.interestsCount); // 1
44. member.interestsCount = 2; // This won’t save the change
45. console.log(member.interestsCount); // 1
46. console.log(member.tasks); // undefined

As you can see, in lines 39 to 43, the member object has all the features of the User class and TeamMember, working as expected. In lines 44 to 45, we try to make changes to member.interestsCount, but it won't work because there is no setter defined. And line 46 shows that accessing member.tasks results in undefined because we didn't define a getter for it.

You cannot use member.constructor to access the constructor of the TeamMember defined in line 14. It is for accessing the member object’s constructor function, in this case, TeamMember.

And now let's see how to add a new method, eat(), to the User class:

User.prototype.eat = function () {
console.log('What will I have for lunch?');
};
member.eat(); // What will I have for lunch?

You still need to add it to the prototype object of User. If you add it directly to User as follows, you will get TypeError:

User.sleep = function () {
console.log('Go to sleep');
};
member.sleep(); // Uncaught TypeError: member.sleep is not a function
User.sleep(); // Go to sleep

It is because as a result of writing in this way that you add sleep as a property of the User class itself or, more precisely, the User constructor function itself. And you might have already noticed that sleep becomes a static method of the User class. When using the class syntax, when you define a method, behind the scene, JavaScript adds it to its prototype object, and when you define a static method, JavaScript adds it to the constructor function:

console.log(User.prototype.hasOwnProperty('eat'));  // true
console.log(User.hasOwnProperty('sleep')); // true

Enhanced object literals

In ES6, object literals support setting prototypes, shorthand assignments, defining methods, making super calls, and computing properties with expressions.

Let's see the following example, which creates an advisor object with a TeamMember object as its prototype:

1.  const advice = 'Stay hungry. Stay foolish.';
2.
3. let advisor = {
4. __proto__: new TeamMember('Adam', ['Consulting']),
5. advice,
6. greeting () {
7. super.greeting();
8. console.log(this.advice);
9. },
10. [advice.split('.')[0]]: 'Always learn more'
11. };

Line 4, assigning the object of TeamMember to the advisor object's __proto__ property makes advisor an instance of TeamMember:

console.log(TeamMember.prototype.isPrototypeOf(advisor));  // true
console.log(advisor instanceof TeamMember); // true

Line 5 is a shorthand assignment of advice:advice. Line 7 is creating the greeting() method of TeamMember, inside which it will invoke the greeting method of TeamMember:

advisor.greeting();   // I' m Adam. Welcome to the team!
// Stay hungry. Stay foolish.

In line 10, the Stay hungry property is calculated with bracket notation. And to access this property, in this case, because the property name contains a space, you need to use bracket notation, like this—advisor['Stay hungry'].

Arrow functions

ES6 introduces arrow functions as a function shorthand, using => syntax. Arrow functions support statement block bodies as well as expression bodies. When using an expression body, the expression's result is the value that the function returns.

An arrow syntax begins with function arguments, then the arrow =>, and then the function body. Let's look at the following different variations of arrow functions. The examples are written in both ES5 syntax and ES6 arrow function syntax:

const fruits = [{name: 'apple', price: 100}, {name: 'orange', price: 80}, {name: 'banana', price: 120}];

// Variation 1
// When no arguments, an empty set of parentheses is required
var countFruits = () => fruits.length;
// equivalent to ES5
var countFruits = function () {
return fruits.length;
};

// Variation 2
// When there is one argument, parentheses can be omitted.
// The expression value is the return value of the function.
fruits.filter(fruit => fruit.price > 100);
// equivalent to ES5
fruits.filter(function(fruit) {
return fruit.price > 100;
});

// Variation 3
// The function returns an object literal, it needs to be wrapped
// by parentheses.
var inventory = fruits.map(fruit => ({name: fruit.name, storage: 1}));
// equivalent to ES5
var inventory = fruits.map(function (fruit) {
return {name: fruit.name, storage: 1};
});

// Variation 4
// When the function has statements body and it needs to return a
// result, the return statement is required
var inventory = fruits.map(fruit => {
console.log('Checking ' + fruit.name + ' storage');
return {name: fruit.name, storage: 1};
});
// equivalent to ES5
var inventory = fruits.map(function (fruit) {
console.log('Checking ' + fruit.name + ' storage');
return {name: fruit.name, storage: 1};
});

There is an additional note regarding variation 3. When an arrow function uses curly brackets, its function body needs to be a statement or statements:

var sum = (a, b) => { return a + b };
sum(1, 2); // 3

The sum function won't work as expected when it is written like this:

var sum = (a, b) => { a + b };
sum(1, 2); // undefined
// Using expression will work
var sum = (a, b) => a + b;
sum(1, 2); // 3

Arrow functions have a shorter syntax and also many other important differences compared with ES5 function. Let's go through some of these differences one by one.

No lexical this

An arrow function does not have its own this. Unlike an ES5 function, that will create a separate execution context of its own, an arrow function uses surrounding execution context. Let's see the following shopping cart example:

1.  var shoppingCart = {
2. items: ['Apple', 'Orange'],
3. inventory: {Apple: 1, Orange: 0},
4. checkout () {
5. this.items.forEach(item => {
6. if (!this.inventory[item]) {
7. console.log('Item ' + item + ' has sold out.');
8. }
9. })
10. }
11. }
12. shoppingCart.checkout();
13.
14. // equivalent to ES5
15. var shoppingCart = {
16. items: ['Apple', 'Orange'],
17. inventory: {Apple: 1, Orange: 0},
18. checkout: function () {
19. // Reassign context and use closure to make it
20. // visible to the callback passed to forEach
21. var that = this
22. this.items.forEach(function(item){
23. if (!that.inventory[item]) {
24. console.log('Item ' + item + ' has sold out.');
25. }
26. })
27. }
28. }
29. shoppingCart.checkout();

In line 6, this refers to the shoppingCart object itself, even it is inside the callback of the Array.prototype.forEach() method. As you can see in line 21, with the ES5 version, you need to use closure to keep the execution context available to the callback function.

And because an arrow function does not have a separate execution context, when it is invoked with Function.prototype.call(), Function.prototype.apply(), or Function.prototype.bind() method, the execution context that passed in as the first argument will be ignored. Let's take a look at an example:

1. var name = 'Unknown';
2. var greeting = () => {
3. console.log('Hi, I\'m ' + this.name);
4. };
5. greeting.call({name: 'Sunny'}); // I'm Unknown
6. greeting.apply({name: 'Tod'}); // I'm Unknown
7. var newGreeting = greeting.bind({name: 'James'});
8. newGreeting(); // I'm Unknown

As you can see from line 3, in an arrow function, this always resolves to its surrounding execution context. The call(), apply(), or bind() method has no effect on its execution context.

Unlike ES5 functions, arrow functions do not have their own arguments object. The arguments object is a reference to the surrounding function's arguments object.

Because arrow functions use its surrounding execution context, they are not suitable for defining methods of objects. 

Let's see the following shopping cart example, which uses an arrow function for the checkout:

1.  var shoppingCart = {
2. items: ['Apple', 'Orange'],
3. inventory: {Apple: 1, Orange: 0},
4. checkout: () => {
5. this.items.forEach(item => {
6. if (!this.inventory[item]) {
7. console.log('Item ' + item + ' has sold out.');
8. }
9. })
10. }
11. }
12. shoppingCart.checkout();

In line 4, we change checkout to an arrow function. And because an arrow function uses its surrounding execution context, this in line 5 no longer references the shoppingCart object and it will throw Uncaught TypeError: Cannot read property 'forEach' of undefined.

The preceding shopping cart example is written with object literals. Arrow functions do not work well when defining object methods using a prototype object either. Let's see the following example:

1.  class User {
2. constructor(name) {
3. this.name = name;
4. }
5. }
6. User.prototype.swim = () => {
7. console.log(this.name + ' is swimming');
8. };
9. var user = new User();
10. console.log(user.swim()); // is swimming

As you can see from the output, in line 7this does not reference the user object. In this example, it references the global context.

No prototype object

Arrow functions do not have prototype objects, hence, they are not constructor functions. And they cannot be invoked with a new operator. An error will be thrown if you try that. Here's an example:

const WorkoutPlan = () => {};
// Uncaught TypeError: WorkoutPlan is not a constructor
let workoutPlan = new WorkoutPlan();
console.log(WorkoutPlan.prototype); // undefined

Default parameter value

In ES6, you can define the default values of a function's parameters. This is quite a useful improvement because the equivalent implementation in ES5 is not only tedious but also decreases the readability of the code.

Let's see an example here:

const shoppingCart = [];
function addToCart(item, size = 1) {
shoppingCart.push({item: item, count: size});
}
addToCart('Apple'); // size is 1
addToCart('Orange', 2); // size is 2

In this example, we give the parameter size a default value, 1. And let's see how we can archive the same thing in ES5. Here is an equivalent of the addToCart function in ES5:

function addToCart(item, size) {
size = (typeof size !== 'undefined') ? size : 1;
shoppingCart.push({item: item, count: size});
}

As you can see, using the ES6 default parameter can improve the readability of the code and make the code easier to maintain.

Rest parameters

In ES5, inside a function body, you can use the arguments object to iterate the parameters of the function. In ES6, you can use rest parameters syntax to define an indefinite number of arguments as an array.

Let's see the following example:

1.  // Using arguments in ES5
2. function workout(exercise1) {
3. var todos = Array.prototype.slice.call(arguments,
workout.length);
4. console.log('Start from ' + exercise1);
5. console.log(todos.length + ' more to do');
6. }
7. // equivalent to rest parameters in ES6
8. function workout(exercise1, ...todos) {
9. console.log('Start from ' + exercise1); // Start from
//Treadmill
10. console.log(todos.length + ' more to do'); // 2 more to do
11. console.log('Args length: ' + workout.length); // Args length: 1
11. }
12. workout('Treadmill', 'Pushup', 'Spinning');

In line 8, we define a rest parameter todos. It is prefixed with three dots and is the last named parameter of the workout() function. To archive this in ES5, as you can see in line 3, we need to slice the arguments object. And in line 11, you can see that the rest parameter todos does not affect the length of the argument in the workout () function.

Spread syntax

In ES6, when the three dot notation (...) is used in a function declaration, it defines a rest parameter; when it is used with an array, it spreads the array's elements. You can pass each element of the array to a function in this way. You can also use it in array literals.

Let's see the following example:

1. let urgentTasks = ['Buy three tickets'];
2. let normalTasks = ['Book a hotel', 'Rent a car'];
3. let allTasks = [...urgentTasks, ...normalTasks];
4.
5. ((first, second) => {
6. console.log('Working on ' + first + ' and ' + second)
7. })(...allTasks);

In line 3, we use spread syntax to expand the urgentTasks array and the normalTasks array. And in line 7, we use spread syntax to expand the allTasks array and pass each element of it as arguments of the function. And the first argument has the value Buy three ticketswhile the second argument has the value Book a hotel.

Destructuring assignment

In ES6, you can use the destructuring assignment to unpack elements in an array, characters in a string, or properties in an object and assign them to distinct variables using syntax similar to array literals and object literals. You can do this when declaring variables, assigning variables, or assigning function parameters.

Object destructuring

First of all, let's see an example of object destructuring:

1. let user = {name:'Sunny', interests:['Traveling', 'Swimming']};
2. let {name, interests, tasks} = user;
3. console.log(name); // Sunny
4. console.log(interests); // ["Traveling", "Swimming"]
5. console.log(tasks); // undefined

As you can see, the name and interests variables defined in line 2 pick up the values of the properties with the same name in the user object. And the tasks variable doesn't have a matching property in the user object. Its value remains as undefined. You can avoid this by giving it a default value, like this:

let {name, interests, tasks=[]} = user;
console.log(tasks) // []

Another thing you can do with object destructuring is that you can choose a different variable name. In the following example, we pick the value of the name property of the user object and assign it to the firstName variable:

let {name: firstName} = user;
console.log(firstName) // Sunny

Array destructuring

Array destructuring is similar to object destructuring. Instead of using curly brackets, array destructuring uses brackets to do the destructuring. Here is an example of array destructuring:

let [first, second] = ['Traveling', 'Swimming', 'Shopping'];
console.log(first); // Traveling
console.log(second); // Swimming

You can also skip variables and only pick the one that you need, like the following:

let [,,third, fourth] = ['Traveling', 'Swimming', 'Shopping'];
console.log(third); // Shopping
console.log(fourth); // undefined

As you can see, we skip the first two variables and only require the third and the fourth. However, in our case, the fourth variable doesn't match any elements in the array and its value remains as undefined. Also, you can give it a default value, like this:

let [,,third, fourth = ''] = ['Traveling', 'Swimming', 'Shopping'];
console.log(fourth); // an empty string

Nested destructuring

Similar to using object literals and array literals to create complex nested data structures with a terse syntax, you can use a destructuring assignment to pick up variables in a deeply nested data structure.

Let's see the following example, in which we only need the user's second interest:

1. let user = {name:'Sunny', interests:['Traveling', 'Swimming']};
2. let {interests:[,second]} = user;
3. console.log(second); // Swimming
4. console.log(interests); // ReferenceError

In line 2, even though we put interests in the destructuring assignment, JavaScript doesn't really declare it. As you can see in line 4, accessing it will raise ReferenceError. What happens here is that JavaScript uses the part on left side of the colon (:), in this case, interests, to extract the value of the property of the same name, and uses the part on the right side to do further destructuring assignments. If you want to extract the interests property, as demonstrated previously, you need to write it in like this: let {interests} = user;.

Here is another example in which the name property of the second element in an array is destructured:

const fruits = [{name:'Apple', price:100},{name:'Orange', price:80}];
let [,{name:secondFruitName}] = fruits;
console.log(secondFruitName); // Orange

Rest elements

You can use the same syntax of the rest parameters in the destructuring assignment to put the remainder of the elements of an array into another array. Here is an example:

let [first, ...others] = ['Traveling', 'Swimming', 'Shopping'];
console.log(others); // ["Swimming", "Shopping"]

As you can see, the second and third items of the array have been copied into the others variable. We can use this syntax to copy an array. However, this is only a shallow clone. When the elements of the array are objects, changes to an object's property of the copied array will be seen in the original array because essentially, the elements of both arrays reference the same object. Here is an example:

1. const fruits = [{name:'Apple', price:100},{name:'Orange', price:80}];
2. let [...myFruits] = fruits;
3. console.log(myFruits[0].name); // Apple
4. myFruits.push({name:'Banana', price:90});
5. console.log(myFruits.length); // 3
6. console.log(fruits.length); // 2
7. myFruits[0].price = 110;
8. console.log(fruits[0].price); // 110

As you can see in line 2, we use the destructuring assignment syntax to copy the fruits array into the myFruits array. And adding a new item to the copied array doesn't affect the original array, as you can see in lines 4 to 6. However, changing the value of the price property from the copied array will be also seen in the original array.

Function parameters destructuring

You can apply a destructuring assignment to function parameters as well. Let's see the following example:

1. function workout({gym}, times) {
2. console.log('Workout in ' + gym + ' for ' + times + ' times');
3. }
4. let thisWeek = {gym: 'Gym A'};
5. workout(thisWeek, 2); // Workout in Gym A for 2 times

As you can see, in line 1, we use object destructuring syntax to extract the gym variable from the first argument of the workout() function. In this way, the argument passed to the workout() function cannot be null or undefined. Otherwise, TypeError will be thrown. You can pass a number, a string, an array, or a function to the workout() function and JavaScript won't complain about it, although you will get undefined as a value for the gym variable.

Let's look at another example, in which we will perform a further destructuring of a destructured variable:

1. function workout({gym, todos}) {
2. let [first] = todos;
3. console.log('Start ' + first + ' in ' + gym);
4. }
5. let today = {gym: 'Gym A', todos: ['Treadmill']};
6. workout(today); // Start Treadmill in Gym A
7. workout({gym: 'Gym B'}) // throw TypeError

In line 1, we do a parameter destructuring of the first argument, and in line 2 we do a further destructuring of the todos variable. In this way, the argument passed to the workout() function must have a todos property and its value is an array. Otherwise, TypeError will be thrown, as you can see in line 7. This is because, in line 2, JavaScript cannot do destructuring on undefined or null. We can improve this by giving todos a default value, as follows:

1. function workout({gym, todos=['Treadmill']}) {
2. let [first] = todos;
3. console.log('Start ' + first + ' in ' + gym);
4. }
5. workout({gym: 'Gym A'}); // Start Treadmill in Gym A
6. workout(); // throw TypeError

As you can see, in line 1, we only give todos a default value and we have to call the workout() function with a parameter. Calling it without any parameters, as in line 6, will still throw an error. It is because JavaScript still cannot do destructuring on undefined to get a value for the gym variable. And if you try to assign a default value to gym itself, such as workout({gym='', ...), it won't work. You need to assign the entire parameter destructuring a default value, like this:

function workout({gym='', todos=['Treadmill']} = {}) {
...
}

Template literals

Template literals provide the ability to embed expressions in string literals and support multiple lines. The syntax is to use the back-tick (`) character to enclose the string instead of single quotes or double quotes. Here is an example:

let user = {
name: 'Ted',
greeting () {
console.log(`Hello, I'm ${this.name}.`);
}
};
user.greeting(); // Hello, I'm Ted.

As you can see, inside the template literals, you can access the execution context via this by using the syntax ${...}. Here is another example with multiple lines:

let greeting = `Hello, I'm ${user.name}.
Welcome to the team!`;
console.log(greeting); // Hello, I'm Ted.
// Welcome to the team!

One caveat is that all the whitespaces inside the back-tick characters are part of the output. So, if you indent the second line as follows, the output wouldn't look good:

let greeting = `Hello, I'm ${user.name}.
Welcome to the team!`;
console.log(greeting); // Hello, I'm Ted.
// Welcome to the team!

Modules

In ES6, JavaScript provides language-level support for modules. It uses export and import to organize modules and create a static module structure. That means you can determine imports and exports at compile time. Another important feature of ES6's module is that imports and exports must be at the top level. You cannot nest them inside blocks such as if and try/catch.

Besides static declarations of imports and exports, there is a proposal to use the import() operator to programmatically load modules. The proposal is, at the time of writing, at stage 3 of the TC39 process. You can checkout the details at https://github.com/tc39/proposal-dynamic-import.

To create a module, all you need to do is to put your JavaScript code into a .js file. You can choose to use tools such as Babel (http://babeljs.io) to compile ES6 code into ES5, together with tools such as webpack (https://webpack.js.org) to bundle the code together. Or, another way to use the module files is to use <script type="module"> to load them into browsers. 

Export

Inside a module, you can choose to not export anything. Or, you can export primitive values, functions, classes, and objects. There are two types of exports—named exports and default exports. You can have multiple named exports in the same module but only a single default export in that module.

In the following examples, we will create a user.js module that exports the User class, a tasks.js module that tracks the count of total completed tasks, and a roles.js module that exports role constants.

Let's have a look at user.js file:

1. export default class User {
2. constructor (name, role) {
3. this.name = name;
4. this.role = role;
5. }
6. };

In this module, we export the User class inline as the default export by placing the keywords export and default in front of it. Instead of declaring an export inline, you can declare the User class first and then export it at the bottom, or anywhere that is at the top level in the module, even before the User class.

Let's have a look at roles.js file:

1. const DEFAULT_ROLE = 'User';
2. const ADMIN = 'Admin';
3. export {DEFAULT_ROLE as USER, ADMIN};

In this module, we create two constants and then export them using named exports in a list by wrapping them in curly brackets. Yes, in curly brackets. Don't think of them as exporting an object. And as you can see in line 3, we can rename things during export. We can also do the rename with import too. We will cover that shortly.

Let's have a look at tasks.js file:

1. console.log('Inside tasks module');
2. export default function completeTask(user) {
2. console.log(`${user.name} completed a task`);
3. completedCount++;
4. }
5. // Keep track of the count of completed task
6. export let completedCount = 0;

In this module, in line 2, we have a default export of the completeTask function and a named export of a completedCount variable in line 6.

Import

Now, let's create a module app.js to import the modules we just created.

Let's have a look at app.js file:

1.  import User from './user.js';    
2. import * as Roles from './roles.js';
3. import completeTask from './tasks.js';
4. import {completedCount} from './tasks.js';
5.
6. let user = new User('Ted', Roles.USER);
7. completeTask(user);
8. console.log(`Total completed ${completedCount}`);
9. // completedCount++;
10. // Only to show that you can change imported object.
11. // NOT a good practice to do it though.
12. User.prototype.walk = function () {
13. console.log(`${this.name} walks`);
14. };
15. user.walk();

In line 1, we use default import to import the User class from the user.js module. You can use a different name other than User here, for example, import AppUser from './user.js'. default import doesn't have to match the name used in the default export.

In line 2, we use namespace import to import the roles.js module and named it Roles. And as you can see from line 6, we access the named exports of the roles.js module using the dot notation.

In line 3, we use default import to import the completeTask function from the tasks.js module. And in line 4, we use named import to import completedCount from the same module again. Because ES6 modules are singletons, even if we import it twice here, the code of the tasks.js module is only evaluated once. You will see only one Inside tasks module in the output when we run it. You can put default import and named import together. The following is equivalent to the preceding lines 3 and 4:

import completeTask, {completedCount} from './tasks.js';

You can rename a named import in case it collides with other local names in your module. For example, you can rename completedCount to totalCompletedTasks like this:

import {completedCount as totalCompletedTasks} from './tasks.js';

Just like function declarations, imports are hoisted. So, if we put line 1 after line 6 like this, it still works. However, it is not a recommended way to organize your imports. It is better to put all your imports at the top of the module so that you can see the dependencies at a glance:

let user = new User('Ted', Roles.USER);        
import User from './user.js';

Continue with the app.js module. In line 7, we invoke the completeTask() function and it increases the completedCount inside the tasks.js module. Since it is exported, you can see the updated value of completedCount in another module, as shown in line 8.

Line 9 is commented out. We were trying to change the completedCount directly, which didn't work. And if you uncomment it, when we run the example later, you will see TypeError, saying that you cannot modify a constant. Wait. completedCount is defined with let inside the tasks.js module; it is not a constant. So what happened here?

Import declarations have two purposes. One, which is obvious, is to tell the JavaScript engine what modules need to be imported. The second is to tell JavaScript what names those exports of other modules should be. And JavaScript will create constants with those names, meaning you cannot reassign them.

However, it doesn't mean that you cannot change things that are imported. As you can see from lines 12 to 15, we add the walk() method to the User class prototype. And you can see from the output, which will be shown later, that the user object created in line 6 has the walk() method right away.

Now, let's load the app.js module in an HTML page and run it inside Chrome.

Here is the index.html file:

1. <!DOCTYPE html>
2. <html>
3. <body>
4. <script type="module" src="./app.js"></script>
5. <script>console.log('A embedded script');</script>
6. </body>
7. </html>

In line 4, we load app.js as a module into the browser with <script type="module">, which is specified in HTML and has the defer attribute by default, meaning the browser will execute the module after it finishes parsing the DOM. You will see in the output that line 5, which is script code, will be executed before the code inside app.js.

Here are all the files in this example:

/app.js
/index.html
/roles.js
/tasks.js
/user.js

You need to run it from an HTTP server such as NGINX. Opening index.html directly as a file in Chrome won't work because of the CORS (short for Cross-Origin Resource Sharing) policy, which we will talk about in another chapter.

If you need to spin up a simple HTTP server real quick, you can use http-serverwhich requires zero configuration and can be started with a single command. First of all, you need to have Node.js installed and then run npm install http-server -g. Once the installation completes, switch to the folder that contains the example code, run http-server -p 3000and then open http://localhost:3000 in Chrome.

You will need to go to Chrome's Developer Tools to see the output, which will be similar to the following:

A embedded script
Inside tasks module
Ted completed a task
Total completed 1
Ted walks

As you can see from the output, the browser defers the execution of the module's code, while the script code is executed immediately, and the tasks.js module is only evaluated once.

Starting from ES6, there are two types in JavaScript—scripts and modules. Unlike scripts code, where you need to put 'use strict'; at the top of a file to render the code in strict mode, modules code is automatically in strict mode. And top-level variables of a module are local to that module unless you use export to make them available to the outside. And, at the top level of a module, this refers to undefined. In browsers, you can still access a window object inside a module.

Promises

Promises are another option in addition to callbacks, events for asynchronous programming in JavaScript. Before ES6, libraries such as bluebird (http://bluebirdjs.com) provided promises compatible with the Promises/A+ spec. 

A promise represents the eventual result of an asynchronous operation, as described in the Promises/A+ spec. The result would be a successful completion or a failure. And it provides methods such as .then(), and .catch() for chaining multiple asynchronous operations together that would make the code similar to synchronous code that is easy to follow.

The features of ES6 promises are a subset of those provided by libraries such as bluebird. In this book, the promises we use are those defined in the ES6 language spec unless otherwise specified.

Let's look at an example in which we will get a list of projects from the server and then get tasks of those projects from the server in a separate API call. And then we will render it. The implementation here is a simplified version for demonstrating the differences between using callbacks and promises. We use setTimeout to stimulate an asynchronous operation.

First of all, let's see the version that uses callbacks:

1.  function getProjects(callback) {
2. // Use setTimeout to stimulate calling server API
3. setTimeout(() => {
4. callback([{id:1, name:'Project A'},{id:2, name:'Project B'}]);
5. }, 100);
6. }
7. function getTasks(projects, callback) {
8. // Use setTimeout to stimulate calling server API
9. setTimeout(() => {
10. // Return tasks of specified projects
11. callback([{id: 1, projectId: 1, title: 'Task A'},
12. {id: 2, projectId: 2, title: 'Task B'}]);
13. }, 100);
14. }
15. function render({projects, tasks}) {
16. console.log(`Render ${projects.length} projects and
${tasks.length} tasks`);
17. }
18. getProjects((projects) => {
19. getTasks(projects, (tasks) => {
20. render({projects, tasks});
21. });
22. });

As you can see in lines 18 to 22, we use callbacks to organize asynchronous calls. And even though the code here is greatly simplified, you can still see that the getProjects(), getTasks(), and render() methods are nested, creating a pyramid of doom or callback hell.

Now, let's see the version that uses promises:

1.  function getProjects() {
2. return new Promise((resolve, reject) => {
3. setTimeout(() => {
4. resolve([{id:1, name:'Project A'},{id:2, name:'Project B'}]);
5. }, 100);
6. });
7. }
8. function getTasks(projects) {
9. return new Promise((resolve, reject) => {
10. setTimeout(() => {
11. resolve({projects,
12. tasks:['Buy three tickets', 'Book a hotel']});
13. }, 100);
14. });
15. }
16. function render({projects, tasks}) {
17. console.log(`Render ${projects.length} projects and ${tasks.length} tasks`);
18. }
19. getProjects()
20. .then(getTasks)
21. .then(render)
22. .catch((error) => {
23. // handle error
24. });

In lines 1 to 15, in the getProjects() and getTasks() method, we wrap up asynchronous operations inside a Promise object that is returned immediately. The Promise constructor function takes a function as its parameter. This function is called an executor function, which is executed immediately with two arguments, a resolve function and a reject function. These two functions are provided by the Promise implementation. When the asynchronous operation completes, you call the resolve function with the result of the operation or no result at all. And when the operation fails, you can use the reject function to reject the promise. Inside the executor function, if any error is thrown, the promise will be rejected too.

A promise is in one of these three states:

  • Pending: The initial state of a promise
  • Fulfilled: The state when the operation has completed successfully
  • Rejected: The state when the operation didn't complete successfully due to an error or any other reason

You cannot get the state of a promise programmatically. Instead, you can use the .then() method of the promise to take action when the state changes to fulfilled, and use the .catch() method to react when the state changed to rejected or an error are thrown during the operation.

The .then() method of a promise object takes two functions as its parameters. The first function in the argument is called when the promise is fulfilled. So it is usually referenced as onFulfilledand the second one is called when the promise is rejected, and it is usually referenced as onRejected. The .then() method will also return a promise object. As you can see in lines 19 to 21, we can use .then() to chain all the operations. The .catch() method in line 22 is actually a syntax sugar of .then(undefined, onRejected). Here, we put it as the last one in the chain to catch all the rejects and errors. You can also add .then() after .catch() to perform further operations.

The ES6 Promise also provides the .all(iterable) method to aggregate the results of multiple promises and the .race(iterable) method to return a promise that fulfills or rejects as soon as one of the promises in the iterable fulfills or rejects.

Another two methods that ES6 Promise provides are the .resolve(value) method and the .reject(reason) method. The .resolve(value) method returns a Promise object. When the value is a promise, the returned promise will adopt its eventual state. That is when you call the .then() method of the returned promise; the onFulfilled handler will get the result of the value promise. When the value is not a promise, the returned promise is in a fulfilled state and its result is a value. The .reject(reason) method returns a promise that is in a rejected state with the reason passed in to indicate why it is rejected.

As you might have noticed, promises do not help you write less code, but they do help you to improve your code's readability by providing a better way of organizing code flow.

Summary

In this chapter, you learned the differences between the JavaScript language and the Java language. Keep these differences in mind. They can help you to avoid pitfalls when you write JavaScript code.

You also learned the basics of ES6. ES6 mastery is considered to be one of the basic skill sets that a web developer should have. You can write less code and also better code with ES6.

In the next chapter, you will learn the fundamental concepts of Vue.js 2, and you will be able to understand how Vue.js 2 works internally and become a master of Vue.js.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Connect application’s frontend and backend with Vue, Vuex, and Spring Boot
  • Leverage the latest web standards to enhance code performance, readability, and cross-compatibility
  • Build secure full-stack web applications with Spring Security

Description

Building Applications with Spring 5 and Vue.js 2, with its practical approach, helps you become a full-stack web developer. As well as knowing how to write frontend and backend code, a developer has to tackle all problems encountered in the application development life cycle – starting from the simple idea of an application, to the UI and technical designs, and all the way to implementation, testing, production deployment, and monitoring. With the help of this book, you'll get to grips with Spring 5 and Vue.js 2 as you learn how to develop a web application. From the initial structuring to full deployment, you’ll be guided at every step of developing a web application from scratch with Vue.js 2 and Spring 5. You’ll learn how to create different components of your application as you progress through each chapter, followed by exploring different tools in these frameworks to expedite your development cycle. By the end of this book, you’ll have gained a complete understanding of the key design patterns and best practices that underpin professional full-stack web development.

Who is this book for?

Building Applications with Spring 5.0 and Vue.js 2.0 is for you if you are developer who is new to Vue.js or Spring. It is assumed that you have some knowledge of HTML, CSS, and Java.

What you will learn

  • Analyze requirements and design data models
  • Develop a single-page application using Vue.js 2 and Spring 5
  • Practice concept, logical, and physical data modeling
  • Design, implement, secure, and test RESTful API
  • Add test cases to improve reliability of an application
  • Monitor and deploy your application to production
Estimated delivery fee Deliver to Denmark

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Oct 26, 2018
Length: 590 pages
Edition : 1st
Language : English
ISBN-13 : 9781788836968
Vendor :
Pivotal
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Denmark

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Publication date : Oct 26, 2018
Length: 590 pages
Edition : 1st
Language : English
ISBN-13 : 9781788836968
Vendor :
Pivotal
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 115.97
Building Applications with Spring 5 and Vue.js 2
€36.99
Software Architecture with Spring 5.0
€41.99
Vue.js 2 Design Patterns and Best Practices
€36.99
Total 115.97 Stars icon
Banner background image

Table of Contents

16 Chapters
Modern Web Application Development - This Is a New Era Chevron down icon Chevron up icon
Vue.js 2 - It Works in the Way You Expected Chevron down icon Chevron up icon
Spring 5 - The Right Stack for the Job at Hand Chevron down icon Chevron up icon
TaskAgile - A Trello-like Task Management Tool Chevron down icon Chevron up icon
Data Modeling - Designing the Foundation of the Application Chevron down icon Chevron up icon
Code Design - Designing for Stability and Extensibility Chevron down icon Chevron up icon
RESTful API Design - Building Language Between Frontend and Backend Chevron down icon Chevron up icon
Creating the Application Scaffold - Taking off Like a Rocket Chevron down icon Chevron up icon
Forms and Validation - Starting with the Register Page Chevron down icon Chevron up icon
Spring Security - Making Our Application Secure Chevron down icon Chevron up icon
State Management and i18n - Building a Home Page Chevron down icon Chevron up icon
Flexbox Layout and Real-Time Updates with WebSocket - Creating Boards Chevron down icon Chevron up icon
File Processing and Scalability - Playing with Cards Chevron down icon Chevron up icon
Health Checking, System Monitoring - Getting Ready for Production Chevron down icon Chevron up icon
Deploying to the Cloud with Jenkins - Ship It Continuously Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela