Functions Expression vs Declaration


Declaring functions might seem to be trivial but in the world of Javascript,there are a lot of misconceptions around it .I will try and demistify about what exactly goes on .

1.We will start off with this code snippet.


var fn = function(){
exprFn();
declaredFn();
var exprFn = function(){
console.log("Expression Function ran");
}
function declaredFn(){
console.log("Declared Function ran")
}
}
fn();

Does this work ? No . It says exprFn is undefined.
Conclusion:The reason being even though the variable declaration is hoisted at the top.The expression assigning the function to exprFn did not and hence we are trying to invoke undefined() and hence it is throwing an error.Lets correct it,which will take us to our next point.


2.


var fn = function(){
declaredFn();
var exprFn = function(){
console.log("Expression Function ran");
};
exprFn();
function declaredFn(){
console.log("Declared Function ran")
}
}
fn();

The result is

Declared Function ran
Expression Function ran
declaredFn() apparently was invoked before it was even declared.
Conclusion:This is because function declarations like variable get hoisted.Hence the declaredFn’ s declaration statement was hoisted and hence declaredFn was already declared.function declarations are parsed and evaluated before any other expressions are. Even if declaration is positioned last in a source, it will be evaluated foremost any other expressions contained in a scope


 

3.


var fn = function(){
declaredFn();
test();
var exprFn = function test(){
console.log("Expression Function ran");
};
exprFn();
function declaredFn(){
console.log("Declared Function ran")
}
}
fn();

We have changed the function a bit .We basically have named the anonymous function assigned to exprFn to test.It is called a named function expression.But the above code doesn’t work.
ReferenceError: test is not defined
As named function expression are also not hoisted.


 

4.


var fn = function(){
var exprFn = function test(){
console.log("Expression Function ran");
console.log("inner:expression",typeof exprFn)
console.log("inner:function name",typeof test)
};
exprFn();
console.log("outer:expression",typeof exprFn);
console.log("outer:function name",typeof test);
}
fn();

If you run the above piece of code you will see
Expression Function ran
inner:expression function
inner:function name function
outer:expression function
outer:function name undefined
So you see ,the function identifier (name) is not accessible by the outer scope.The specs says that the identifier should not be available in the scope enclosing it.Hence “test” is undefined

Now that we know the difference between function expression and function declaration.The question we will try and answer is

why the following doesn’t work as an IIFE: function foo(){ }();.

It doesn’t work because brackets after a function declaration doesn’t invoke the function.The function can only be immediately invoked if its an expression.


1+function foo(){console.log("I got executed");}()

The result is
I got executed
NaN
The spec says that the plus operator expects 2 expression.Hence our function declaration is transformed into a function expression and the extra brackets at the end invoke them.Similarly the common practice of using IIFE is putting it within brackets.


(function (){console.log("I got executed");})()

The extra brackets just turns the function declaration into an expression and makes it invokable.You can transform your function declaration to an expression by putting it in an operator that expects expression.Js would do the rest for you 🙂

Instance Creation Part 3


The previous post we dealt with how “new” works. In this post we will talk about how Object.create works.


var constructorObj = { a:1};
var obj = Object.create(constructorObj)

If we print obj, we will see Object {a: 1}

Firstly, obj is of type Object and not constructorObj.Secondly lets go a little deeper and try


Object.getPrototypeOf(obj)

Object {a: 1}

So basically the constructorObj got attached to the prototype of the new object.That is all it does

Now lets change our constructorObj


constructorObj.a = 2

print obj
Object {a: 2} .So the prototype shares the same object.Any value you change on the object also reflects on the instances.And also obj.constructor points to the native Object

Lets see how it behaves with instances created with new


var constructorFn = function(){this.a=1};
constructorFn.prototype.field1 = "test";
var obj = new constructorFn()
var newObj = Object.create(obj);

Now if we print newObj.We will see

Object {a: 1, field1: “test”}

So the way this happens is newObj[[prototype]]==obj,obj[[prototype]] = constructorFn[[prototype]].

So now if we print Object.getPrototypeOf(Object.getPrototypeOf(newObj)); we will see exactly what we expect Object {field1: “test”} .

Lastly lets see what happens when we pass a function


var obj = Object.create(constructorFn)

If we print obj , we will see Function {}
typeof obj is “object”
obj instanceof Function //true

So what exactly happens ? Well the function gets attached to the prototype .
Object.getPrototypeOf(obj) gives us the original constructorFn. Unlike new there is no change of the this object and hence obj does not get a copy of the properties.

Optimizing Selectors in JQuery.


jQuery uses a selector engine called Sizzle.Sizzle has various ways of selecting elements. Selecting elements is one of the fundamental part of jQuery, hence it’s important we learn how to optimize our selectors. jQuery selector Engine runs from right to left. Being specific on the left hand side has a lot less value than being specific on the right hand side.

$(“.parent .child”)//This is how the selector engine works.

A common misconception is that being accurate makes the selector works faster as it knows where to find the DOM element. But that is not the case. jQuery has a very different way in which it handles selecting by id or selecting by class.

<ul class=”listing”>

<li class=”bullet”>

<h3 class=”mainelement”> This is a test<h3>

</li>

<ul>

 

$(‘ul.listing li.bullet h3.mainelement’) //though is the most specific is not the fastest.

The fastest selector is simply the class name by itself.

$(.parent child)//Fastest

Anything else is telling jQuery to do more work than necessary. Starting from the right that is all that we need to get the set of elements.

<ul class=”listing”>

<li id=”bullet”>

<h3 class=”mainelement”> This is a test<h3>

</li>

<ul>

Now since we have an id. We can further bring down the time required by selecting with ID.

$(‘#bullet .mainelement’)//Sizzle operates differently when the first selector is ID

But to really speed things up, we can use

$(‘#bullet’).children(‘.mainelement’) or $(‘#bullet’).find(‘.mainelement’)

The latter being the fastest. To understand the discrepancy we must look into the jQuery Source. When the only part of the selector is an ID jQuery uses document.getElementById(id) which drastically reduces the time taken.

$(‘p#randomid’) //jQuery will use getElementsByTagName(), then iterate though the array of elements for the above selector.

var div = $(‘#randomId’);ßjQuery will use getElementById() for the above selector

From the source code we can see, the fastest selector is

$(‘ ‘)//Returns an empty jQuery object.

$(‘body’)//Next in line, jQuery converts this to document.body

$(‘#id’)//Third fastest, jQuery converts this to document.getElementById(‘id’)

 

Now to distinguish between children() and find(), Children only looks at the immediate children of the node, while find traverses the entire DOM below the node. But in general cases find is faster. children () internally makes calls to sibling(), filter(), and goes through a few more regexes than find() does. find () and children() fulfill different needs, but in the cases where find() and children() would output the same result, it’s better to use find().