We were discussing the let keyword in the Part 1 of this
series. We discussed what the advantages and how we can use let keyword in the
code. However, let keyword has a problem it does not support hoisting, means if
you have declared a variable using let keyword in the mid of the block it would
not be available in the part above the declaration of the let keyword.
So you always make
sure that let is declared at the top of the block.
As we discussed earlier let keyword kind of Hack the scope
implicitly. We can always write the code to make sure when we see we can
explicitly identify that this block is a scope. The example given the in the
Part 1 of this series used the implicit way. To use the explicit way do it like
this
function foo(bar) {
"use
strict"
let (test = bar) {
console.log(test) // "bar"
}
console.log(baz)
// reference error
}
However, this syntax is rejected by the committee. we can use some other way to make sure we see the
block scope in the code as we read the code.
function foo(bar) {
"use
strict"
/*let */
{
let test = bar
console.log(test) // "bar"
}
console.log(baz)
// reference error
}
This is one way to do it. Keyle Simpson have
created this great tool to help you with block scoping it is called Let-er .
So, as we started to talk about tools you might want to take
a look at traceur-compiler it generates ES 5 code from ES 6 code. As there is development going on in ES 6
you should start writing your code in ES 6 and use a transpiler to convert
the ES 6 code to ES 5. You can use grunt-traceur . Other than this you might wanna take a look at the tools for ES 6.
Hoisting
this keyword
Default and Implicit Binding
Explicit Binding
New keyword
Hoisting
Hoisting is a concept which is developed to understand how
JavaScript works when we declare the variables and functions. Take a look at
the code below
console.log(a);
console.log(b);
var a = 5;
var b = 10;
If you see the above code and try to infer the output of the
first 2 consoles than you will think that there will be undeclared error, but not it will be not. Output of
first 2 logs will be undefined. Why? You can think of the above code as below.
var a = 5;
var b = 10;
console.log(a);
console.log(b);
a = 5;
b = 10;
All the declarations will be moved to the top. Hence output
will be undefined not undeclared. So if we say all the declarations that means
variable declarations and function declarations. There are function
declarations and function expressions. Function
declaration is
function foo()
{
}
And function expression is
var d = function() {
console.log('hello');
}
Function expressions are not Hoisted.
So if we have a code like this
a = b();
b = d();
function b() {
console.log('hello');
}
d = function() {
console.log('world');
};
Here is the output of the code
function declarations
are hoisted before the variable declarations
If
you remember C/C++ programming? We use to write header files and put them at
the top of our implementation files. That is manual hoisting, we are putting
all the declarations at the top of the code. JavaScript do that for us implicitly.
Another
use of Hoisting is mutual recursion.
this keyword
Each and every function in the JavaScript have reference to
the current context of the function with this
keyword. Function can have the current context depending upon
Default and Implicit Binding
Default binding is how the function is called. You can take
a look at the code below and you should be able to understand the default
binding.
This binding default
In above example you can see if we are calling the function
hello without any decoration of object it is printing the global name variable.
Which means this keyword is set to the global object. However, this is not true
in strict mode. In Strict mode you will get an error as shown below
Because in Strict mode value of this will be undefined. Not the
global variable if we are calling the function without any decoration.
That’s default binding, we have called foo using obj1 and
obj2 that is implicit binding.
With this I would like to point out something that we might
think should work but it actually not possible take a look at the below code
function hello() {
var one = "hello";
world();
}
function world(){
console.log(this.one + "
world")
}
var one =
"one";
hello();
think about what would be the output of the code?
You might think it would be “hello world” right? If you are
right than you are wrong but if you are wrong than you are right.. J
Output of the above code will be “one world” because the
binding if you try to understand the code you will know. Hello is called with
context set to global and in turn world will be called with global context which
have variable one with value “one”.
Explicit Binding
We can do explicit binding using the call and apply
functions. Both takes the first parameters as the object which you want to be the
in the function. They have different behavior with the parameters but they
behave similar way with this.
There is another problem which we see is when we lost the
context of this in the function. Very common problem is if you are making an
Ajax request and in your success method you want to call the function of context
in which ajax was made. However, it does not happen. So to make sure you have
same context all over the function try to keep an original reference to the
this keyword in separate variable.
Var self = this;
As the first statement of the function. This way it will be
hard binding and you will always have the reference to the original this.
Or what else we can do? We can use the bind function in ES
5. If you are not using ES 5, than you can go to MDN bind page and check the polyfill for this bind function.
New keyword
What happen when we add a new keyword in front
of a function call? When we put a new keyword below are things which happen
- A new object is created
- A new object is linked
- Newly created object will be set as a context of the function.
- And the newly created object will be returned if the function otherwise is not returning anything.
So how do we decide which binding is going to take place
when we see a piece of code and see that there are multiple things going on
here
There is a precedence
- If the function is called with new keyword than use the newly created object.
- Was there any explicit binding? If yes than use the object passed.
- Is there any owning object which called the function? If yes, use that object.
- We default to the global object if not in strict mode otherwise to undefined.
Happy Coding!!
No comments:
Post a Comment