I am trying to build a shopping cart for learning purpose. I have following codes
HTML
<div id="MyCart" class="product-cart">
<ul>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
</div>
js
var cart = (function () {
cart.createCart = function (cartId) {
console.log(cartId);
cartId = document.getElementById(cartId);
}
return cart;
}());
var shoopingCart = cart.createCart("MyCart");
But this code throws following error
Uncaught TypeError: Cannot set property 'createCart' of undefined
After spending few hours in internet and following some tutorials I did following changes to the code and then it started working.
But still I dont understand what i have done here
var cart = (function (cart) {
cart.createCart = function (cartId) {
console.log(cartId);
cartId = document.getElementById(cartId);
}
return cart;
}(cart || {}));
var shoopingCart = cart.createCart("MyCart");
Can some one please explain me why the code started to work after passing cart || {}
expression into the anonymous function? Some detailed explanation would be great. :)
A self-invoking (also called self-executing) function is a nameless (anonymous) function that is invoked immediately after its definition. An anonymous function is enclosed inside a set of parentheses followed by another set of parentheses () , which does the execution. (function(){ console.
Self-Invoking Functions A self-invoking expression is invoked (started) automatically, without being called. Function expressions will execute automatically if the expression is followed by (). You cannot self-invoke a function declaration.
Another use case of anonymous functions is to invoke the function immediately after initialization, this is also known as Self Executing Function. This can be done by adding parenthesis we can immediately execute the anonymous function.
Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function.
So without the variable passed into the scope.
var cart = (function (cart) {
// can't add a property or method onto undefined.
cart.createCart = function (cartId) {
console.log(cartId);
cartId = document.getElementById(cartId);
}
return cart;
}()); // without any value here ^ cart will be undefined.
var shoopingCart = cart.createCart("MyCart");
However, if you pass the variable to the context:
var cart = (function (cart) {
// cart now is an object which you can attach a property or method
cart.createCart = function (cartId) {
console.log(cartId);
cartId = document.getElementById(cartId);
}
return cart;
}(cart || {})); // pass in cart, or if it is null a new object {}
var shoopingCart = cart.createCart("MyCart");
So an IIFE looks like this:
(function () { })();
so ignoring the function
you get ( )();
in that second pair of parenthesis you pass the parameters to the function
in the first set. This is because IIFE creates a whole new clean scope. This is why we use IIFE because it can isolate global variables that we use in them.
so if you have this:
<script>
var someGlobalVariable = "hey";
(function () {
// using someGlobalVariable here will be fine
var myIIFEScopedVariable = "ho";
})();
// trying to access myIIFEScopedVariable here will fail because again, it hasn't been defined here.
</script>
So IIFE's are great for controlling what you have in scopes.
The cart || {}
is a JavaScript null coalesce, so it says, pass in cart but if it is null give it an empty object
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With