//strict mode in js var actNow = function(){ 'use strict'; newVariable = 9; }; actNow();/* Uncaught ReferenceError: newVariable is not defined. */ /* Due to strict mode we have to define the variable newVariable with keyword var as the strict mode will not allow us to place the variable in the global scope. */ /* If you use 'use strict' mode in the global space while using thir party libraries you may face problems if the those libraries are not meant to be used in the strict mode. */ //******************************************************* var actNow = function(){ //'use strict'; newVariable = 9; }; actNow(); /* Here we have commented the line with the strict mode so we get no error from this snippet and the variable will be placed in the global space. */ //******************************************************* //The 'delete' operator removes a variable from the context var actNow = function(){ var newVar = 9; delete newVar; }; actNow();//No error and the code works. //******************************************************* //The 'delete' operator is not allowed in the strict mode. var actNow = function(){ 'use strict'; var newVar = 9; delete newVar; }; actNow();/* Uncaught SyntaxError: Delete of an unqualified identifier in strict mode. */ /* If we declare a variable in strict mode, we can't get rid of it. */ //******************************************************* /* The following code gives no error as we are not in strict mode inspite of the fact that both the arguments have the same name. */ var actNow = function(){ var fn = function(x, x){ //Do something here. }; }; actNow();//no error //******************************************************* var actNow = function(){ 'use strict' var fn = function(x, x){ //Do something here. }; }; actNow(); /* Uncaught SyntaxError: Duplicate parameter name not allowed in this context */ //******************************************************* 'use strict'; var obj ={}; with(obj){ console.log('using with statement'); }; //*******************************************************
Saturday, 9 April 2016
The strict mode in javascript
Friday, 8 April 2016
Some global functions in javascript
Some global functions in javascript
var value = parseInt('1234'); console.log(value); var value = parseInt('b1234'); console.log(value); var value = parseInt('12b34'); console.log(value);//When a NaN is hit it stops further parsing but 12 is shown on the console var value = parseInt('1234.9'); console.log(value);//1234 - It ends parsing when it hits the decimal point. Doesn't do rounding for us. var value = parseInt('C000', 16);//16 is the base/radix so c000 is a hexadecimal number. console.log(value); var value = parseFloat('1234.999'); console.log(value);//1234.99 //Parsing the float with exponential number. //Move the decimal to one place to the left var value = parseFloat('1234e-1'); console.log(value);//123.4 var value = isFinite(Number.POSITIVE_INFINITY); console.log(value);//false var value = isFinite(Number.NEGATIVE_INFINITY); console.log(value);//false var value = isFinite(42); console.log(value);//true var value = isFinite('42'); console.log(value);//true var value = isNaN(NaN); console.log(value);//true var value = isNaN(3 / 0); console.log(value);/* false because isNaN(infinity) is false. Most of the other programming languages will give an exception when dividing a number by zero but js does not give exception. */ var value = isNaN(Number.POSITIVE_INFINITY); console.log(value);//false var value = isNaN(Number.NEGATIVE_INFINITY); console.log(value);//false var value = isFinite( 3 / 0); console.log(value);//false because 3 / 0 gives infinity var path = "\\start\\"; console.log(encodeURI(path));//%5Cstart%5C var path = "\\start\\+"; console.log(path);//\start\+ var path = "\start\+"; console.log(decodeURI(path));//start+ var path = "\\start\\"; console.log(encodeURIComponent(path));//%5Cstart%5C var path = "\\start\\+"; console.log(encodeURIComponent(path));//%5Cstart%5C%2B var path = "%5Cstart%5C%2B"; console.log(decodeURIComponent(path));//\start\+ /* The following global function should be avoided as it opens systems to injection attack and other attacks. */ var globalVar = 'qwerty'; var code = 'console.log(globalVar);'; eval(code);
The Math object in javascript - some important functions
The Math object in javascript - some important functions
//Math object in js console.log(Math.PI); console.log(Math.abs(-36)); console.log(Math.ceil(23.12));//24 console.log(Math.floor(23.99));//23 console.log(Math.trunc(34.67));//34 console.log(Math.max(0,67,-3,"99"));//99 the string is converted implicitly to a number console.log(Math.min(-23, 0,56)); console.log(Math.pow(3,4));//81 console.log(Math.random());//between 0 and 1 console.log(Math.sqrt(64)); console.log(Math.sqrt(-64));//NaN
the string object in javascript - some important functions
The string object in javascript - some important functions
//Some important functions in the string object in js var value = 'Some string'; console.log(value.charAt(6));//t console.log(value.concat(' concatenated with this one.')); console.log(value.includes(' ')); console.log(value.endsWith('ing')); console.log(value.endsWith('ing '));/* false - There is a space at the end which is not trimmed by function endsWith() */ console.log(value.indexOf('r')); console.log(value.indexOf('Z'));//-1 as Z is not found in the string value console.log(value.lastIndexOf('s'));//starts at the end of the string and goes backwards console.log(value.slice(5));//string - start at index 5 and return a slice of the original string console.log(value.slice(5, 8));//str - start at index 5 and returna slice up to but not including index 8 //Give me the final 3 characters starting from the end of the string console.log(value.slice(-3)); // - ing - negative argument shows starting backwards. //Splitting a string into an array var str = "This is a string that we will split into an array on the basis of a space character and has 22 words."; console.log(str.split(' ').length);//22 because we are splitting using a space and that makes it 22 elements console.log(str.substr(40, 9));//an array - start at index 40 and return 8 characters. /* If you want a string that starts at index i and ends at index j but j is not included then use str.substring(i, j) function instead of substr(beginningIndex, numberOfCharactersToReturn) function. */ console.log(str.substring(40, 65));//character at 65 is not included.
Event bubbling in javascript
Event bubbling and capturing
Event bubbling and capturing are two ways of event propagation in the HTML DOM API, when an event occurs in an element inside another element, and both elements have registered a handle for that event. The event propagation mode determines in which order the elements receive the event.
With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.
With capturing, the event is first captured by the outermost element and propagated to the inner elements.
Capturing is also called "trickling", which helps remember the propagation order:
trickle down, bubble up
Back in the old days, Netscape advocated event capturing, while Microsoft promoted event bubbling. Both are part of the W3C Document Object Model Events standard (2000).
Here is the html:
<div id="div1" class="element1">The blue square <div id="div2" class="element2"> The red square </div> </div>
Here is the css:
.element1{
background-color: blue;
height: 200px;
width: 200px;
position: relative;
top: 2px;
left: 20px;
}
.element2{
background-color: red;
height: 100px;
width: 100px;
position: relative;
top: 40px;
left: 50px;
}
background-color: blue;
height: 200px;
width: 200px;
position: relative;
top: 2px;
left: 20px;
}
.element2{
background-color: red;
height: 100px;
width: 100px;
position: relative;
top: 40px;
left: 50px;
}
Here is the javascript:
/* Event bubbling. */
/* The html used in this js file is given in the html file. */
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
};
div1.addEventListener('click', clickHandler, false);//bubbling
div2.addEventListener('click', clickHandler, false);//bubbling
/*
The false as the thrid argument in the method call above causes the bubbling. First event is handled
by div2 and then it it is bubbled to its parent div1. If we want it the other way round i.e., we wnat div1
to handle the event first and then bubble it to div2 then we need to set the boolean value to true as the
thrid argument in the call to addEventListener().
*/
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing
/* If we wnat the event to be handled by the parent but not by the child then we can stop the propagation of
the event by using method stopPropgagation() as shown below. In this case the parent will handle the event
and stop further propagation of the event to the child.
*/
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
event.stopPropagation();
/*
If we want to prevent the default action when something is clicked then we include the followin one line of code also.
*/
event.preventDefault();
};
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing
/* The html used in this js file is given in the html file. */
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
};
div1.addEventListener('click', clickHandler, false);//bubbling
div2.addEventListener('click', clickHandler, false);//bubbling
/*
The false as the thrid argument in the method call above causes the bubbling. First event is handled
by div2 and then it it is bubbled to its parent div1. If we want it the other way round i.e., we wnat div1
to handle the event first and then bubble it to div2 then we need to set the boolean value to true as the
thrid argument in the call to addEventListener().
*/
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing
/* If we wnat the event to be handled by the parent but not by the child then we can stop the propagation of
the event by using method stopPropgagation() as shown below. In this case the parent will handle the event
and stop further propagation of the event to the child.
*/
var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');
var clickHandler = function divClickHandler(event){
console.log(this.id);
event.stopPropagation();
/*
If we want to prevent the default action when something is clicked then we include the followin one line of code also.
*/
event.preventDefault();
};
div1.addEventListener('click', clickHandler, true);//capturing
div2.addEventListener('click', clickHandler, true);//capturing
Thursday, 7 April 2016
The Event Object in javascript
The event object in javascript is created by the javascript runtime engine which gets passed to an event handler. Here are some key properties of this object:
1. bubbles - true or false - based upon whether this event bubbles up to their parents or not.
2. cancelable - true or false - will let us know whether we can cancel any kind of propagation of this event.
3. currentTarget - is the DOM (Document Object Model) element that we are currently looking at.
4. defaultPrevented - true or false - tells us if preventDefault() was called.
5. detail - This property holds extra information about the event.
6. eventPhase - 1/2/3 - 1 means that it is the capture phase which is the opposite of bubbling - going in the other direction of bubbling. 2 means that we are currently at the target. 3 means that we are in the process of bubbling.
7. preventDefault() - To prevent the browser from executing any default behavior. An example would be preventing the submit button on a form submit the form. Another example would be preventing the browser following a link in an anchor tag.
8. stopPropagation() - will stop all event-capturing and bubbling.
9. stopImmediatePropagation - will stop all event-capturing and bubbling but will also make sure that no more handlers get called.
10. target - the original target of this event. For example if we click on a button and the event bubbles up from parent to parent to parent, target will be set to that original button.
11. trusted - true or false - true if event comes from the browser. false if event is triggered through the javascript code written by the programmer.
12. type - name of the event. For example it would be the string "click" for a click event.
Query selectors in javascript
Here is the html code that will be used in the javascript on this page.
<article id="article1" class="my-custom-class"><h3>
Title of the page goes here.
</h3>
<p>
This is paragraph one.
</p>
<p class="special">
This is paragraph two.
</p>
<p class="special">
This is paragraph three.
</p>
</article>
Here is the javascript code that uses the html code above.
//Query selectors /*
Use MDN, the Mozilla Developers Network to learn more about other functions and properties.
*/ var element = document.querySelector('article'); console.log(element);//prints on the console the complete article tag var element = document.querySelector('#article1'); console.log(element); //Getting only the first paragraph var element = document.querySelector('.special'); console.log(element); //Getting all the paragraphs in the document var elements = document.querySelectorAll('.special'); console.log(elements);
Document object in javascript - introduction
Here is the html code that has been used in the javascript code on this page.
<article id="article1" class="my_new_class">
<h3>
Demonstrating how to get an element fron an html document in javascript
</h3>
<p>
This is paragraph one.
</p>
<p>
This is paragraph two.
</p>
<p class="new_point">
This is paragraph three.
</p>
<p class="new_point">
This is paragraph four.
</p>
</article>
Here is the javascript code that uses the html code above.
var element = document.getElementById('article1'); console.log(element);//We get the element in the document that has id=article1 var elements = document.getElementsByTagName('p'); console.log(elements);//We get an array of all the elements that has a tag of p i.e., paragraph var element = document.getElementsByTagName('h3'); console.log(element);//We get an array of all the elements with heading set to h3 var elements = document.getElementsByClassName('new_point'); console.log(elements);//We get an array of our two paragraph elements with class=new_point //*************************************************************************** /* Once we get an element from a document then we can get access to any of its attributes also. */ var e = document.getElementById('article1'); console.log(e.getAttribute('class'));//my_new_class //We can dynamically set an attribute also. e.setAttribute('class', 'my_old_class'); console.log(e.getAttribute('class'));//my_old_class //We can get all the child nodes of an element. console.log(e.childNodes); /* We get on the console [text, h3, text, p, text, p, text, p.new_point, text, p.new_point, text] the array has text 6 times because we have spaces before the h3, and all the paragraph elements and white space is represented as text. */
The location object in javascript
/* The location object lets us look at the browser's URL location. */ console.log(location.href); // https://fiddle.jshell.net/_display/ console.log(location.host); //fiddle.jshell.net console.log(location.port); //port number console.log(location.protocol); // https: //redirecting to another page/website but it depends on your browsing settings. location.assign('https://www.google.com');//directs browser tot he page passed as argument.
System Dialogs in javascript - alert, confirm, and prompt
//System dialogs //1. alert alert('Hello jsfiddle.net'); //2. confirm - with ok and cancel button ok button for the if is true case and cancel button for the else case if(confirm('Do you want to leave this page?')){ console.log('You chose to leave the page.'); } else{ console.log('You chose to stay on the page.'); } //3. prompt - with an ok and a cancel button var input = prompt('Enter Your address please!'); if(input != null && input != '') console.log(input); else { console.log('You did not enter any address'); }
timer in javascript
//Timer related code snippets in js console.log(new Date().getSeconds()); //e.g., 49 seconds /* function setTimeout() is a global object window and we do not need to prefix it with window.*/ setTimeout(function() { console.log(new Date().getSeconds()); }, 1000 );/* 1000 milliseconds of delay should be observed before calling the function setTimeout after the internal function has been called. */ /* I got 6 7 because there were 6 seconds in to the minute and then it was 7 seconds into the minute. Note that the 7 appears after an interval of 1 second after the 6 appears on the console. If I delete the ', 1000' then I will instead get 6 6 as no delay is being observed. */ //******************************************************* console.log(new Date().getSeconds()); /* Assigning the id of the timer to a variable so that we use that id later on to clear the timer and prevent it from being activated. */ var id = setTimeout(function(){ console.log(new Date().getSeconds()); }, 1000 ); clearTimeout(id); /* After executing the code above we get only one number as our timer is prevented being activated by the clearTimeout() method. */ //******************************************************* /* In the code snippet given below we pass a funciton to method setInterval() and that internal function will be called over and over again untill the if condition is true and it is then when the function clearInterval(id) will be called to stop calling the internal function. */ console.log(new Date().getSeconds()); var id = setInterval(function(){ var seconds = new Date().getSeconds(); console.log(seconds); if(seconds === 30)//shutting down the timer when there are 30 seconds into the minute clearInterval(id);//id exists in the outer function. }, 1000 ); //*******************************************************
Window object in javascript
console.log(window.screenLeft + ', ' + window.screenTop);//0,0 but depends on where the window is positioned on your screen /* innerWidth is where your html document is showing. The brower ususall has some kind of frame and that is included in the outer width. */ console.log(window.innerWidth + ', ' + window.outerWidth);//100, 1280 window.open('http://www.google.com', '_blank');/*Popup might be blocked so you will not get a new window but might get an indication that a poping up window has been blocked.*/
Recursive functions in javacript - an introduction
//Recursion in javascript //functions /* Making a json object that uses anonymous function instead of a named funciton which causes problem in a scenario in which we make another variable ftn2 to point to the same function ftn by assigning ftn2 to ftn. Then we set ftn to null and we lose our reference to the recrusive call to ftn inside the funciton ftn. If we use a named function then the problem gets solved and recursion works. */ var orgChart = { name: 'Dilshad', subordinates: [{ name: 'Rafaqat', subordinates: [{ name: 'Sardar', subordinates: [] }, { name: 'Shaukat', subordinates: [] }] }] }; //Writing an anonymous function that uses recursion. var ftn = function(topEmployee) { console.log(topEmployee.name); console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length); /* Calling itself recrusively for each employee to check it s(he) has subordinates. */ for (var i = 0; i < topEmployee.subordinates.length; i++){ console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": "); //Recursive call to ftn in the line below. ftn(topEmployee.subordinates[i]); } }; //calling the funciton ftn and passing it the json object representing the organization chart. //********************************** //ftn(orgChart); //********************************** /* Here is the output of the function above: Dilshad Number of subordinates of Dilshad: 1 Dilshad's subordinate # 1: Rafaqat Number of subordinates of Rafaqat: 2 Rafaqat's subordinate # 1: Sardar Number of subordinates of Sardar: 0 Rafaqat's subordinate # 2: Shaukat Number of subordinates of Shaukat: 0 */ //The problem with the anonymous function above starts when we do the following two lines. //********************************** //var ftn2 = ftn; //ftn = null; //ftn2(orgChart); //********************************** /* We get an error after the first top employee of the organization chart as shown as the recursive call fails because we have set ftn to null and we are still calling it in the recrusive call inside the body of the function. Dilshad Number of subordinates of Dilshad: 1 Dilshad's subordinate # 1: Uncaught TypeError: ftn is not a function */ /* The solution is simple - use a named function instead of an anonymous funciton as shown below: */ //Writing a named function that uses recursion. var ftn = function showAllEmployees(topEmployee) { console.log(topEmployee.name); console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length); /* Calling itself recrusively for each employee to check it s(he) has subordinates. */ for (var i = 0; i < topEmployee.subordinates.length; i++){ console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": "); //Recursive call to ftn in the line below. showAllEmployees(topEmployee.subordinates[i]); } }; /* Now the code works even if we do the following. */ var ftn2 = ftn; ftn = null; ftn2(orgChart); /* But don't forget to comment the lines above which were causing errors. The lines between //********************************** and //********************************** should be commented */
Here is the output on the console:
Dilshad Number of subordinates of Dilshad: 1 Dilshad's subordinate # 1: Rafaqat Number of subordinates of Rafaqat: 2 Rafaqat's subordinate # 1: Sardar Number of subordinates of Sardar: 0 Rafaqat's subordinate # 2: Shaukat Number of subordinates of Shaukat: 0
Immediately invoked function expressions (IIFEs)
//IIFEs - Immediately invoked function expressions //IIFEs don't pollute the global environment. (function(){ console.log('Executed!'); })(); //************************************************************* /* We can move the last pair of parenthesis () before the semicolon inside the parenthesis containing hte whole function. This works the same way as the code snippet given above. */ (function(){ console.log('Executed again!'); }()); //************************************************************* //IIFEs don't pollute the global environment. (function(){ var employeeName = 'Jack'; })(); /* The linew of code below will give error as employeeName has been declared with keyword var inside the function so it does not pollute the global namespace. Its scope is limited to the function only. */ /* console.log(employeeName);//Uncaught ReferenceError: employeeName is not defined */ //************************************************************* /* app in the code below is an object that is empty here but in a real app it will be populated. Most of the libraries in js has a global variable e.g., $ in jQuery. An application has often a variable in the global namespace called app. */ var app = {}; (function (ns) { ns.name = 'None'; })(app);//Passing the global variable app as an argument to the IIFE function. console.log(app.name);//None //************************************************************* var app = {}; var jQuery = {}; /* The way we pass jQuery as a second argument to the IIFE guarantees that the jQuery === $ (the dollar sign). */ (function (ns, $) { ns.name = 'None'; console.log($ === jQuery);//true })(app, jQuery); //************************************************************* /* To make sure that the system's undefined object is set to the undefined object we do as given below: */ var app = {}; var jQuery = {}; (function (ns, $, undefined) { ns.name = 'None'; console.log(undefined);//undefined })(app, jQuery); //************************************************************* //We can also use +, -, or ! with the keyword function instead of parentheses +function(){ var employeeName = 'Jack'; console.log('Executed!');//Executed }(); console.log(employeeName);//Uncaught ReferenceError: employeeName is not defined. //*************************************************************
Wednesday, 6 April 2016
Using anonymous functions might give problems if used recursively in javascript - an example scenario
Recursive functions in javascript
Making a json object that uses anonymous function instead of a named funciton which causes problem in a scenario in which we make another variable ftn2 to point to the same function ftn by assigning ftn2 to ftn. Then we set ftn to null and we lose our reference to the recrusive call to ftn inside the funciton ftn. If we use a named function then the problem gets solved and recursion works.
// Making a json object that uses anonymous function var orgChart = { name: 'Dilshad', subordinates: [{ name: 'Rafaqat', subordinates: [{ name: 'Sardar', subordinates: [] }, { name: 'Shaukat', subordinates: [] }] }] }; //Writing an anonymous function that uses recursion. var ftn = function(topEmployee) { console.log(topEmployee.name); console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length); /* Calling itself recrusively for each employee to check it s(he) has subordinates. */ for (var i = 0; i < topEmployee.subordinates.length; i++){ console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": "); //Recursive call to ftn in the line below. ftn(topEmployee.subordinates[i]); } }; //calling the funciton ftn and passing it the json object representing the organization chart. //********************************** //ftn(orgChart); //********************************** /* Here is the output of the function above: Dilshad Number of subordinates of Dilshad: 1 Dilshad's subordinate # 1: Rafaqat Number of subordinates of Rafaqat: 2 Rafaqat's subordinate # 1: Sardar Number of subordinates of Sardar: 0 Rafaqat's subordinate # 2: Shaukat Number of subordinates of Shaukat: 0 */ //The problem with the anonymous function above starts when we do the following two lines. //********************************** //var ftn2 = ftn; //ftn = null; //ftn2(orgChart); //********************************** /* We get an error after the first top employee of the organization chart as shown as the recursive call fails because we have set ftn to null and we are still calling it in the recrusive call inside the body of the function. Dilshad Number of subordinates of Dilshad: 1 Dilshad's subordinate # 1: Uncaught TypeError: ftn is not a function */ /* The solution is simple - use a named function instead of an anonymous funciton as shown below: */ //Writing a named function that uses recursion. var ftn = function showAllEmployees(topEmployee) { console.log(topEmployee.name); console.log('Number of subordinates of ' + topEmployee.name + ': ' + topEmployee.subordinates.length); /* Calling itself recrusively for each employee to check it s(he) has subordinates. */ for (var i = 0; i < topEmployee.subordinates.length; i++){ console.log(topEmployee.name + "'s subordinate # " + (i + 1) + ": "); //Recursive call to ftn in the line below. showAllEmployees(topEmployee.subordinates[i]); } }; /* Now the code works even if we do the following. */ var ftn2 = ftn; ftn = null; ftn2(orgChart); /* But don't forget to comment the lines above which were causing errors. The lines between //********************************** and //********************************** should be commented */
Monday, 4 April 2016
Returning a function from another function - closures in javascript
closures are used to persist functions in javascript. It helps us to persist functions and access their context. We can have access to the variables inside the functions even when we are outside the function as the function is not garbage-collected due to persistence.
//closures var salaryUpdater = function(salary){ var currentSalary = salary; var generator = function(){ currentSalary *= 2; return currentSalary; }; return generator; }; var updateFtn = salaryUpdater(50000); console.log(updateFtn());//100000 //************************************************************* /* To prove that the function salaryUpdater and its context is persistent we will call it twice and will show that the increment made in the first call remains and the second call increments the salary further. */ var salaryUpdater = function(salary){ var currentSalary = salary; var generator = function(){ currentSalary += 5000; return currentSalary; }; return generator; }; var updateFtn = salaryUpdater(30000); updateFtn(); console.log(updateFtn());//40000 //*************************************************************
Indirectly calling functions using the call() and apply() function in javascript
//Using call() and apply() functions var updateZipCode = function(){ console.log(this);//Window(....) //this points to the global object Window }; updateZipCode(); //************************************************************************ var updateZipCode = function(){ console.log(this);//Object{} }; /* In the line given below we are passing an empty object as parameter to the call mehtod so that inside the function updateZipCode 'this' can refer to it. */ updateZipCode.call({}); //************************************************************************ var updateZipCode = function(){ console.log(this);//Object {zip: "22675"} }; /* In the line given below we are passing an object that has a property zip along with the valu of that property set to 22675 as parameter to the call mehtod so that inside the function updateZipCode 'this' can refer to it. */ updateZipCode.call({zip: '22675'}); //************************************************************************ //We can pass a variable as argument to call() as shown below var updateZipCode = function(){ console.log(this);//Object {zip: "24358"} }; //Making a variable to be passed to the method call() as argument. var zipCode = { zip : '24358' }; updateZipCode.call(zipCode); //************************************************************************ //Using a function that requires arguments. var updateZipCode = function (newZip, country) { console.log(newZip + ' ' + country);//98679 japan }; var zipCode = { zip: '45345' }; /*In the line below we are passing the object zipCode as the first argument which will be associated with the keyword 'this' in the function updateZipCode(). We are also passing the arguments for the neqZip and country. */ updateZipCode.call(zipCode, '98679', 'japan'); //************************************************************************ /* The apply() function gets an array as argument and break down this array in to arguments to pass them to the function updateZipCode(). If we supply a list of arguments instead of an array it will not work. */ var updateZipCode = function(newZip, country){ console.log(newZip + ' ' + country);//29468 japan }; var zipCode = { zip: '34679' }; updateZipCode.apply(zipCode, ['29468', 'japan']); /* If we use apply() but instead of an array, pass it a list then we get the following error: Uncaught TypeError: CreateListFromArrayLike called on non-object */ //updateZipCode.apply(zipCode, '29468', 'japan'); //************************************************************************
'this' keyword in functions and the global space - an exercise on what 'this' refers to in a piece of code
//This file explains the this keyword in functions and the global space but does not explain the use of this in eventhandlers. console.log(typeof this);//object console.log(this === window);/*true. It refers to the window object. Will not works in node as node doesn't have a window object as it works on a server.*/ var name = 'Dilshad'; console.log(this.name);//result ??? console.log(name);//Dilshad //"this" gets assigned to window if we specify it in the global space without attaching it to any object. var updateSalary = function(){ console.log(this === window);//true }; updateSalary(); //************************************************************************************************** var employee = { name: 'Jeff', updateSalary : function (){ console.log(this); /* Object {name: "Jeff"} shows that 'this' refers to the object employee as function updateSalary() is attached to an object employee. */ } }; employee.updateSalary(); //************************************************************************************************** var employee = { name: 'Dilshad', updateSalary: function() { var fn = function () { console.log(this);/* Window {external: Object, chrome: Object, document: document, speechSynthesis: SpeechSynthesis, caches: CacheStorage…} shows that keyword 'this' is attached to the global window. as function window has no object attached to it and therefore the keyword this gets attached to the window. We can ascertain it by using the following line also.*/ console.log(this === window); }; fn(); } }; employee.updateSalary(); //************************************************************************************************** //We have a constructor function given below var Address = function (line1) { this.line1 = line1; console.log(this);//Address {line1: "Chak 79 Street 12"} }; /* Creating a new object using the operator 'new' and calling the constructor and passing it a string. This will attach the keyword 'this' to this newly created object. */ var address = new Address('Chak 79 Street 12'); //************************************************************************************************** var Address = function (line1){ this.line1 = line1; }; /* Creating a function and attaching it to the prototype of the constructor so that all instances created by this constructor can have access to the function to update zip codes in the instance that call this function.*/ Address.prototype.updateZipCode = function(){ //update the zipcode here in the address object created by the constructor Address console.log(this);//Address {line1: "chak 79 Street 12"} }; //creating a new instance/object address var address = new Address('chak 79 Street 12'); address.updateZipCode(); //************************************************************************************************** //**************************************************************************************************
Sunday, 3 April 2016
Constructor functions and their empty prototypes and adding functions to those prototypes in javascript
/* Finding the type of Object in js. Object is of type function in js and not of type Object. Object is a constructor function in js. */ console.log(typeof Object);//function //**************************************************************************************** var Employee = function (name, boss) { this.name = name; this.boss = boss; }; var newEmployee = new Employee('jj', 'jhon jhones'); console.log(typeof newEmployee);//object console.log(newEmployee.name);//jj console.log(newEmployee.boss);//jhon jhones //**************************************************************************************** var Employee = function(name){ this.name = name; }; var e1 = new Employee('jj'); var e2 = new Employee('kk'); var e3 = e1; console.log(e1 == e2);//false console.log( e1 === e2);//false console.log(e1 == e3);//true console.log( e1 === e3);//true //**************************************************************************************** //__ double underscore is called dunder proto and is a kind of hack to enable us to reach the prototype console.log(e1.__proto__ === e2.__proto__);//true /* The line above proves that both the employee objects have the same prototype and that makes it very easy for the programmer to add functionalities to the Employee. We don't have to write a function for the thousand of employee objects instead we just write it once in the prototype of our Employee and all ojbects have acess to it. */ //**************************************************************************************** /* We should not add function to the body of the constructor Employee otherwise it would be duplicated into the body of all those objects that we are creating using this constructor. The following block of code is wrong. */ var Employee = function (name){ this.name = name; this.giveRaise = function(){ //Increase the salary by 10 %. }; }; var e1 = new Employee('jj'); var e2 = new Employee('kk'); console.log(e1.giveRaise === e2.giveRaise);//false /* The line above gives false as both e1 and e2 get their own copies of function giveRaise() when they are created using the constructor Employee. * /* The correct way to do it is to add the function giveRaise to the prototype of the Employee constructor. See later in the code. */ //**************************************************************************************** /* When we work with json objects, we do not have direct access to the prototypes but now when we are working with the Constructor functions we do have access to the prototype. */ console.log(typeof Employee.prototype);//object //**************************************************************************************** //Is Employee.prototype is the same as Object.prototype? console.log(Employee.prototype === Object.prototype);//false /* The line above gives false and that proves that Employee has got its own empty prototype object. In json, each object has its prototype set to Object.prototype but that is not the case when we are dealing with constructor functions. */ //**************************************************************************************** /* The correct way to add a funciton is not to add it to body of the constructor Employee as done above in the code but to add it to the prototype of the connstructor Employee as shown below: */ var Employee = function (name){ this.name = name; this.salary = 25000;//All employees get a start salary of 25 k during creation of an object of type Employee }; Employee.prototype.giveRaise = function(raise){ this.salary += raise; }; var e1 = new Employee('jj'); var e2 = new Employee('kk'); console.log(e1.giveRaise === e2.giveRaise);//true /* Now even if we 50 k employees we don't duplicate the function as we have added it to the prototype of the constructor function and all the employees objects can call it. */ e1.giveRaise(5000); console.log(e1.salary); console.log(e2.salary); //****************************************************************************************
Defining custom properties on an object to have more control.
'use strict'; //We define an empty object. var task = {}; //We define a property on the object task with key as 'text' and value as 'Get this job done!' Object.defineProperty(task, 'text', { value: 'Get this job done!' }); console.log(task.text); //***************************************************************** var task = {}; Object.defineProperty(task, 'text', { value: 'Get this job done!', //By default writable : false. Therfore, we have to set it to true if want o make th property text writable writable: true }); /* If the writable : true is commented out then by default writable : false and we will get TypeError: can not assign to read only property. */ task.text = task.text + ' ... Now!'; console.log(task.text); //***************************************************************** var task = {}; Object.defineProperty(task, 'text', { value: 'Get this job done!', //enumerable is used in for in statements enumerable: true }); for(var f in task){ console.log(f);/* We get text on the console but if we do not set enumerable: false then by default enumberable: false and nothing will be shown on the console.*/ } //***************************************************************** var task = {}; Object.defineProperty(task, 'text', { value: 'Get this job done!', configurable: true }); Object.defineProperty(task, 'text', { value: 'Done!' }); console.log(task.text);/* The output on the console is 'Done!' as configurable: true but if we set configurable: false or just delete that line then by default configurable:false and, therefore, we get Ucaught TypeError: Cannot redefine property: text */ //***************************************************************** //Getter functions var task = { _dueDate: '1/30/2016' }; Object.defineProperty(task, 'dueDate', { get: function(){ return this._dueDate; } }); console.log(task.dueDate); //***************************************************************** //Setter function var task = { _dueDate: '1/30/2016' }; Object.defineProperty(task, 'dueDate', { get: function (){ return this._dueDate; }, set: function (newValue) { this._dueDate = newValue; } }); //The line below will call the setter funciton task.dueDate = '10/28/2016'; console.log(task.dueDate); //***************************************************************** //Assigning multiple properties to a single task var task = {}; Object.defineProperties(task, { // Setting the property text of the object task 'text': { value: 'New Task' }, //setting the property dueDate of the object task 'dueDate': { value: '1/30/2014' } } ); console.log(task.text + ' Due: ' + task.dueDate); var descriptor = Object.getOwnPropertyDescriptor(task, 'text'); console.log(descriptor);//Object {value: "New Task", writable: false, enumerable: false, configurable: false} var descriptor = Object.getOwnPropertyDescriptor(task, 'dueDate'); console.log(descriptor);//Object {value: "1/30/2014", writable: false, enumerable: false, configurable: false} //***************************************************************** //*****************************************************************
Subscribe to:
Posts (Atom)