Good Morning, My name's Rahul dwivedi and I'm your host and one of the speakers today.
Today we're gonna talk about javascript- from ES5 to ES6. And what you can do in Es6 that you can't possibly in ES5.
But before that, Let me introduce myself.
I'm a Javascript developer. I work at Talentica Software as a senior software engineer.
I have an overall experience of 5 years and I have worked with JavaScript(vanilla), Jquery, AngularJs, Angular 2+, react, node in no particular order.
Look at the first code which is written in ES5. There's a little problem there. Your QA doesn't want it. Neither does you client.
I'll give you a hint. What happens when you pass 0 as an argument?
It rreturns 100. My favourite number is 100.
Of course you can correct it. You should change the statement as (if num === undefined or num === null), then num =100
But then you have take extra precautions and care. On the other hand, in ES6 you can just do away with this by defining it in the default parameter.
So, if you believe in this philosophy that Fewer the lines of codes, lesser are the chances of bugs, then ES6 is for you!
As zero is falsy value, it incorrectly prints number of soldiers as 10000 where you were expecting 0.
Actually 'Our baldes are sharp' is the House Bolton's sizil. But, since this is my world, I have changed it to that belonging to house Tully. which is what most of us as developers do. We change the things the way we want.function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5, 2));
// expected output: 10
console.log(multiply(5));
// expected output: 5
As you can see, it's a heck of job in ES5 to create multiline texts. \n\t, +
If you forgot, \n or + anywhere, it will be a mess.
In Es6 though, you just have to wrap the whole text the way you want it to appear with two backticks. New line will be automatically created wherever there is separation
Between the texts in the form of lines.
And if you don't know where to find backticks, it's there on the top left, below esc and just above tab keys.
This is a typical node js code.We're required to extract parameters from the body.
So, 'rat' is extracted from req.body.rat, mouse from req.body.mouse and so on.
While in ES6, All you have to do is to put the keys of the object inside curly braces separating them with commas and there you go!
In case, you want to rename, you just have to put colons and then the alias. For e.g 'rat' is represented by 'rt', mouse by 'ms' and so on.
In case, you don't want to put some keys and values in an object, you can make use of spread operator. 3 dots! So, here Rest object will contain mouse, house and chair.
This works with arrays as well. But make sure the order is correct. Else, eyes become hair, nose becomes ear.
If you want to escape an item, just put a comma in its place.
Just a slight correction here, spread operator has been approved in Es9 and not in Es6. Nevertheless, it's already supported by a lot of browsers and anyway going to be a part of JavaScript.
Destructuring works with nested objects as well.
In this example, book object has a field called properties which itself is an object.
To extract this you just have to put these keys inside curly braces as you just saw. So we have author variable now which will be book.properties.author
You can even put some extra information in the new object or discard any thing that you don't want to destruct.
Here we have added title and discarded garbage from the original object
The first one is a function returning a typical object where keys and values are separated with commas.
In ES6 however, you can just create this object by putting these keys inside two curly braces and those keys will be mapped to their corresponding values in the form of object.
Much more easier to write and read. What happens here is that it checks if the property key has a corresponding variable name and assigns the value of that variable to the property. Note that if no variable has the same name as the property key defined, we'll get an error.
You can get rid of the word function in ES6.
So getTitle() will return the same values in both cases.
Well it just means that the key in an object can be computed.
So in book object you can make use of the variable defined which is name.
So books.title1 will be Digital Fortress
Books.title2 will be Da vinci code and so on
Dan Brown's fans here?
I want you guys to look at these two snippets that are one below the other.
Tell me the output.
The first one prints 'Robert Targaryen' likes to introduce bugs and 'Robert Targaryen' likes to fix bugs. Taking this.name from the global variable while tasks from the object it is inside.
The second one takes both this.name and this.tasks from the object it is inside and prints. "Tyrion Brathon" likes to introduce bugs. "Tyrion Brathon" likes to fix bugs.
So this expected and desired behaviour is achieved using arrow function in ES6.
But why was the unexpected behaviour in the first case? This is because when 'this' is inside an object it is in the scope of that object. However, when it is inside a standalone method, this does not belong to the method it is in, but to the global window object
You might ask why. Well that's the way it is. It’s Javascript. I mean that's the way it was
To explain further, lets look at this code.
Well, I could have get rid of a, b, c and d. Making them anonymous would have been just as alright.
What will be the output? Jon Doe, Jon Snow or Jon Lannister?
Well the output will be Jon Doe as I said, this belongs to the global window object when it is inside a function.
Look at this snippet. I want you guys to focus now.
Actually, you need to be a GOT fan to attend these sessions. Just kidding. Not everone likes it. It's kinda heavier for some people.
How is the execution of this code?
Well. First of all, the global vaiables, objects, functions in this case kingslanding which is an IIFE are pushed on to the stack.
Then the Javascript engine encounters houseStark and pushes it on the stack.
Now what happens at line # 5? This function returns and calls another function which is houseLannisters.
As you can see, houseStark has already returned but it's still there on the stack occupying memory space.
We can very well ged rid of this which is what has been provided in ES6 in the form of Tail call optimisation.
So as soon as a frame is not needed on the stack, it is removed.
Now, you might say, well this is interesting but I don't see this is a huge deal. Well, I tell you this is a big deal. And I'll show you how.
This is a typical method to implement Fibonacci series. Can you guess the result?
It results in an error. 'Maximum call exceeded'. If you look at this code, at line number 4, self call is made and that keeps happening pushing these frames on to the stack.
Now the thing is the stack can not get rid of the previous calls as they are required for the further execution of the program.
Hence, the memory keeps getting occupied until there is none left. The Result? Your console gets painted in red with Maximum call exceeded error. So What can we do about this?
We can optimise our code this way. You can see in this, the function makes a call to itself. However, at any step the previous calls are not required and hence those frames can be
Safely removed from the stack.
Can you tell me the output of this code? Infinity! Whenever javascript engine encounters a number that can not be represented using 64 bits, that reults in Infinity.
As a javascript developer, you might need not write lot of recursive functions. But at some point of time, you definitely do. At that make sure you rememeber this. Make sure your code is tail call optimised.
So Tail call optimization was not supported in ES5 and below so you'd have got the error –Maximum call exceeded even if you write this code in the previous version.
Another interesting stuff is dictionary implementation.
What happens when you set the value of dictionary[index1] as 100.
Dictionary[index2] will also have the value as 100, so will the string representation of object which is "[object Object]"
All of them will print the same thing.
Of course you can fix this by explicitly writing a method with getter and setter. You'll define two arrays one for keys, the other for values. The setter method will check if the key is present in the array key or not. If it is, it will ignore, else it will the set the key. Similary for values.
But even then the time complexity of that method will be O(N), while in case of dictionaries you want time complecity as O(logN) or O(constant).
So how do you do this in ES6?
Well, using map function
So here line# 5 prints 100 , and what about line #6? Guesses? undefined
Another brilliant feature introduced in ES6, which previously was not there, is Promises.
Prior to Es6, you had to make use of some external libraries to implement promises. Now, it's part of JavaScript.
A promise has three stages – Pending, fulffiled or rejected. If it is fulfilled, 'resolve' is called, and if it is rejected, 'reject' is called.
What will be the result of the first snippet? - First it will alert 'non synchronous code', then 'hello' after 4 sec and finally 'promise completed'
So here you can see, your code execution is not blocked.
What happens if you comment out the the line # 2? It will only print 'non synchronous code' and not 'promise completed'. This is because we haven't resolved the promise.
And What if you call 'reject' instead of 'resolve'.? Same thing will happen in that case too. Because we haven't resolved the promise, it won't print 'promise completed'
In case of an error, you would want to make use of 'reject'.
And how to implement reject? well, you can make use of 'then' that you just saw and pass 'null' as the first argument and then the callback function as you can see in the first snippet.
Or, you can use 'catch' shown in the second one.
Then promises support chaining of 'then' as well as you can see in the third snippet.
ES6 introduced let & const keywords.
let and const have a block scope whereas var has function scope. That means let & const will be accessible inside the given block of code where it is declared,
could be for loop, if statement or a function.
This will be clearer from our next example
So if you pass 20 as an age, the first one will throw an error saying status is not defined while the second one will print the output.
So again, in the first one you can see, we have used let variable, so the scope is limited to that within the curly braces enclosing if statement.
While in the second case, status is accessible even outside of the 'if statement'.
So that's it from my side. Now Abhishek will take over.
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-hoisting-js
Error like C.
Precedance
POLL : How many of you know what is hoisting.
Hoisting means lifting up.What is Output of this code and why it's undefined.
This code would have thrown error in language like C.All variable declarations are hoisted to top of function or global context. But not the assignment.
During hoisting function declaration takes precedence over variable declaration.
Variable assignment is not hoisted.
It is recommended to declare all variable at top of the function.
Do you think declarations are really pulled up to the top ?
What will be the output of first slide.
Show output
Hoisting is applicable for both variable and functions.
Functions takes precedence over variable declaration.
Show next code snippet
Function assignments are not hoisted
In first image.In function foo "baz" will be declared on scope of foo and hoisted, So scope of foo will point to local "baz" variable and string "baz" will be printedIn second image
Functions are hoisted as well as declared. So second bar function will overwrite first bar function. Then actual code executes.
This example will be more clear in some time.
In ES6 variable should must be declared first on top otherwise reference error is thrown.
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-closure-js
A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain.
The closure has three scope chains: it has access to its own scope (variables defined between its curly brackets), it has access to the outer function’s variables, and it has access to the global variables.
Closures have access to the outer function’s variable(makeCounter in this case) even after the outer function returns:
Closures store references to the outer function’s variables
Closures store references to the outer function’s variables. They do not store the actual value. That means if the outer function variable value changes, so will the value of inner function.
// 23
// sets empId to 24
// 24
Jeremy is running fast because he is trying to catch the train.
1. We use the 'this' keyword as a shortcut, a referent; it refers to an object; that is, the subject in context, or the subject of the executing code.
2. Consider that there could be another global variable with the name “person.” Then, references to person.firstName could attempt to access the firstName property from the person global variable, and this could lead to difficult-to-debug errors.
* 'this function': function which contains this keyword.
* The "context", when invoking fullName, is the person object(i.e.) when we invoke the fullName () method on the person object.
And the use of "this" inside the fullName() method has the value of the person object.
3. We can use the apply method to set the "this" value explicitly
"this" gets the value of whichever object invokes the "this" Function
So the context is now anotherPerson because anotherPerson invoked the person.fullName () method by virtue of using the apply () method
1. We have a simple object with a clickHandler method that we want to use when a button on the page is clicked
2. The button is wrapped inside a jQuery $ wrapper, so it is now a jQuery object
And the output will be undefined because there is no data property on the button object
since the button ($(“button”)) is an object on its own, and passing the user.clickHandler method to its click() method as a callback
* this inside our user.clickHandler method will no longer refer to the user object. this will now refer to the object where the user.clickHandler method is executed because this is defined inside the user.clickHandler method
And the object that is invoking user.clickHandler is the button object—user.clickHandler will be executed inside the button object’s click method.
Note that even though we are calling the clickHandler () method with user.clickHandler (which we have to do, since clickHandler is a method defined on user), the clickHandler () method itself will be executed with the button object as the context to which “this” now refers. So this now refers to is the button ($(“button”)) object.
We have to bind the clickHandler method to the user object
O/p: Jeremy Gillbert
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-inside_closure-js
1. It is important to take note that closures cannot access the outer function’s this variable by using the this keyword because the this variable is accessible only by the function itself, not by inner functions.
this inside the anonymous function cannot access the outer function’s this, so it is bound to the global window object, when strict mode is not being used.
O/p : Window object
o/p: Jeremy Gillbert is playing at undefined
Ellena Gillbert is playing at undefined
we use a common practice in JavaScript and set the this value to another variable before we enter the forEach method
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-variable_assign-js
This data variable is a global variable
this data variable is a property on the user object
Assign the user.showData to a variable
When we execute the showUserData function, the values printed to the console are from the global data object, not from the data object in the user object
o/p: Jeremy Gillbert 17 (from the global data array)
We can fix this problem by specifically setting the this value with the bind method
Bind the showData method to the user object
o/p: T. Woods
Now we get the value from the user object, because the this keyword is bound to the user object
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-borrow_methods-js
1. We have two objects. One of them has a method called avg () that the other doesn't have. So we will borrow the (avg()) method
2. the gameController.avgScore property will be set to the average score from the appController object "scores" array
3. The avg method’s “this” keyword will not refer to the gameController object, it will refer to the appController object because it is being invoked on the appController.
1. Note that we are using the apply () method, so the 2nd argument has to be an array—the arguments to pass to the appController.avg () method.
2. The avgScore property was successfully set on the gameController object, even though we borrowed the avg () method from the appController object
3. appController.avgScore is still null; it was not updated, only gameController.avgScore was updated
The gameController object borrows the appController’s avg () method. The “this” value inside the appController.avg () method will be set to the gameController object because we pass the gameController object as the first parameter to the apply () method. The first parameter in the apply method always sets the value of “this” explicitly.
https://gist.github.com/chouhand/cb804a656ac16b92772c4b25043d1fc8#file-thisvalue_apply-js
// global variable for demonstration
//global function
Add all the scores and return the total
The "this" keyword inside avg function will be bound to the global object, unless we set the "this" with Call or Apply
// If we execute the avg function thus, "this" inside the function is bound to the global window object:
Proof that the avgScore was set on the global window object
// To set the "this" value explicitly, so that "this" is bound to the gameController,
// We use the call () method:
// reset the global avgScore
o/p: //global avgScore
// 46.4
the first argument to call () sets the this value. In the preceding example, it is set tothe gameController object. The other arguments after the first argument are passed as parameters to the avg () function.
To set the "this" value explicitly, so that "this" is bound to the gameController, We use the call () method:
Note: The apply and call methods are almost identical when setting the this value except that you pass the function parameters to apply () as an array, while you have to list the parameters individually to pass them to the call () method
we usually use bind in class constructor
ES6 I.e the sixth version of Javascript launched in June 2015 introduced Classes in JS.
We will see how we use classes in ES6 ? Why were the classes introduced ? What happens in JS when we declare a class ? How can we replicate same in ES5 ?
Feel free to ask any doubts. I will try to answer as per my knowledge.
How many have used classes in JS ? How many have used it in other langs (Java, C++). Any diff ?
Class keyword introduced in ES6. This was just a syntax change as Javascript internally is still a functional language. It is just like a change in candy wapper. We will see that in a few minutes how that is happening
Similar but not same. Like it allows classes but not interfaces. Inheritance behaves differently etc etc. Details would be covered in later sessions.
Constructor keyword introduced. Every class gets to declare only one constructor function. Special function used to initialize class members. Can't initialize without it. Optional.
class weaponX{
constructor(){
this.name = name;
this.powers = [];
}
Class syntax is much easier to read and simpler to write. We will see that when we see the transpiled code from ES6 to ES65. While it used to take several lines of code and in depth knowledge of JS Prototypes earlier, any newbie developer can write the same behavior in a few lines.
Even for a developer coming from a Java background, it has become easier to understand and write code in Javascript.
It has become less error prone now. The code looks cleaner and easy to debug as well. Having said that, it is still necessary to know the intricacies of classes in JS.
Sometimes we come across unexpected behavior and this knowledge comes in handy. So let's deep dive.
Classes internally are just functions.
Functions in JS get an in-built property called 'prototype'. Function.prototype will give you its contents. This is the trick that enables "class" behaviour in JS.
class weaponX{
constructor(name = "Wolverine"){
this.name = name;
this.powers = [];
}
setPower(power){
this.powers.push(power);
}
getPowers(){
return this.powers;
}
}
let logan = new weaponX();
console.log(logan .__proto__);
console.log(weaponX.prototype)
console.log(weaponX.prototype == logan .__proto__);
Simpler in ES6. Not required in depth knowledge
'prototype is used to define new functions'
'prototype of base is assigned to prototype of derived'. Also __proto__ is set. This is a rough translsation to make it understandable. No error handling is used.
Use whiteboard and console if needed.