You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The JS engine is a 2 pass system. In the first pass,
it is going to hoist or assign a memory location
to variables and functions and in the 2nd pass,
it's going to assign a value.
Variables are partially hoisted and functions are fully hoisted. In the above
(function(){console.log("Does this hoist")})()
The above function does not hoist. const and let are not
hoisted. It's going to throw a reference error.
What about function expressions?
varapp=function(){console.log('How does this hoist?');}
The variable app is going to be hoisted and assigned
undefined. If I run sing2() before it is defined, I get
an error saying that the function is not defined.
Difference between a function expression and declaration
Function expressions are defined at runtime while
function declarations are defined at parse time.
When a function is invoked, we get the this keyword and
arguments. The arguments keyword give us an object with
the argument passed as property values.
Now we want the arguments to be an array so that we can
perform some computations on them. Now the arguments are
an array.
One major issue with global variables is that we can have collissions. To avoid
this JS developers used an IIFE.
An IIFE is an function expression which looks like this:
(function(){})();
Using thi design pattern, we can define all our variables in a local scope. We can aalso see
that the function expression is immediately invoked. We cannot do the same
with a function declaration. What's the benefit of this?
(function(){vara='Is this available outside'})();console.log(a)//reference error
This is really powerful though. I can encapsulate the behaviour of the
underlying function and only return the values neeed. We still used
a global namespace but we kept it from polluting.
varz=1varscript1=(function(){return5;})()
JQuery made use of the IIFE pattern
// Importing jquery here<scriptsrc="http://code.jquery.com/......"></script>// Now jquery has been added to our window object<script>varscript1=(function(what){what('h1').click(function(){what('h1').hide();})functiona(){return5;}return{a:a}})(jQuery)</script>
We can also do something like this
script.a()//5
this keyword
this is the object that the function is a property of.
The increment function has a common behavior for both objects. This code is not scalable to 10000
users as we are making copies for each user.
proto
Mental Model
Store the increment function in just one object and have the interpreter,
if it doesn't find the function on user1, look up to that object if it's
there.
How to make this link?
functionuserCreator(name,score){letnewUser=Object.create(userFunctionStore)newUser.name=name;newUser.score=score;returnnewUser;}letuserFunctionStore={increment:function(){this.score++}login:function(){console.log('You are logged in');}}letuser1=userCreator('Will',3);letuser3=userCreator('Tim',4);user1.increment();
Object.create(userFunctionStore)
The above snippet essentially creates an empty object with
a bond to the userFunctionStore. This is how the object that the function returns.
The returned object from the UserCreator function looks like
this {name:'Gidi', score:10, __proto__:User.prototype}
When the increment function is called, the this inside the function is
set to user1. However, the this inside function add1 is set to the window
object. The arrow function has it's this assignment lexically scoped.
Javascript uses the proto link to give objects, functions
and array a bunch of bonus functionality. All objects by
default have proto
With Object.create, we overrule the default __proto__
reference to Object.prototype and replace it with functionStore.
= But functionStore is an object so it has a __proto__
reference to Object.prototype. We just intercede in the chain.
If we look for a method which is not present in both
the Function and the Object, the it throws an error. The proto on the Object's object points
to null
Subclassing
Mental Model
Suppose we have a user with name and score properties. We want another user to have these properties with extended features.
paidUser.displayFees();// paidUser does not find displayFees defined as a method.// Look's in proto// It finds a reference to paidUserFunction which has the displayFees method defined.
paidUser.sayName();//Method's not defined in the object body//Look in __proto__//Does not find it//Look in the __proto__ of the referenced object//Finds it
functionuserCreator(name,score){this.name=name,this.score=score}userCreator.prototype.sayName=function(){console.log('I am '+this.name)}userCreator.prototype.increment=function(){this.score++;}constuser1=newUserCreator('Phil',3);user1.sayName();
Here we use the new creator which creates an object implicitly with it's
__proto__ reference to userCreator.prototype.
The userCreator.call() sends this as reference to the newly created object in userCreator. This userCreator function
assigns the values name and score to the object which is essentially one layer above. Hence if we observe, the userCreator
function does not return the object as we have not used a new keyword. It is just manipulating the object in the
paidUserCreator.
The paidUserCreator function returns an object which looks like this
The extends keyword also sets the proto reference
to the userCreator object-function combo.
paidUser1=newpaidUserCreator('Alyssa',8,25)
When we call the paidUserCreator,
we are going to assign the arguments to the parameters.
The this assignment is uninitialized. We call super with the paidName and the paidScore parameter
values.
The this in paidUserCreator is going
to be assigned to the return value of calling super.
this=super('Alyssa',8)//Behind the scenesthis=Reflect.construct(userCreator,[Alyssa,8],paidUserCreattor)//Which is essentially doing thisthis=newuserCreator('Alyssa',8)
We are going to create the new object inside
of our class Usercreator unlike our above approach where
we created a new object in paidUserCreator and created
a side effect.
One gotcha to note here is whenever we create
an object using the new keyword infront of userCreator,
the returned object's proto reference is set
to userCreator.prototype.
However, with the super keyword overrides the proto
referece in our new object to paidUserCreator.prototype
which we did manually before.
The new object returned is assigned to
this in paidUserCreator.
There is a difference in how let and const hoist. let is hoisted in it's block scope but don't get initialized to undefined.
Type Coercion
Whenever there's a divergence between what your brain thinks
is happening and what the computer does, that's where bugs enter
the code.
Fundamental Pillars of JavaScript
Types
Scope
Objects
Coercion
Primitive Datatypes
undefined
string
number
boolean
object
symbol
typeof operator
varv;typeofv;//undefinedv="1"typeofv;//stringv=2typeofv//numberv=true;typeofv//booleanv={}typeofv//objectv=Symbol();typeofv;//symboltypeofdoesntExist;//undefinedvarv=null;typeofv;// object OOPS!!v=function(){}typeofv// function
undefined vs undeclared
undefined means that there is a variable declared and at the moment it has no value
undeclared means it's never been created in any scope we have
access to.
NaN
Essentially NaN means a special sentinel value that indicates
a nonnumeric value.
isNaN(myAge);//falseisNaN(myCatsAge)//trueisNaN('my sons age')//true
The third example in the above code return true for a string input.
The isNaN function is going to coerce the input to a Number
and return true if it's a NaN value.
The ES6 specification gives us the correct result for
the input of the type NaN.