Try to do as many of the exercises as possible, in the order listed. You may skip an exercise if it is impossible to accomplish the task described (for technical reasons). If you have trouble with an exercise, contact the instructor for help – do not just skip the exercise! You may work with a partner, but each of you must submit your individual work. Work should be done electronically on this document (cut and paste as needed but be careful of incorrect characters). Anything that involves code should be tried out in VS Code before submitting (you may cut and paste directly from VS Code). Submit work before the next class. If you cannot submit by this time, try to do so as soon as possible.
You may wish to open the presentation slides for convenience of viewing and copy-paste. When asked by the instructor do the lab exercises indicated. If you get done early, feel free to go on. If you are not done before the instructor indicates the next exercise, raise your hand and explain where you are at. Later parts often depend on completing previous parts so do not let yourself get behind and expect to catch up!
Note: Whenever you see something like <Your Name> and it’s not obviously an HTML tag, it means replace this with you own information as indicated inside. e.g. replace <Your Name> with Joe (or whatever your name is).
For exercises that do not ask specific questions but have you perform tasks, copy any code you created and the output as your answer to the exercise. Some exercises ask for explanations. Make notes for your answer and complete these after class before submitting. Do not try to make complete answers if it keeps you from progressing!
Do all your code work in VS Code. Copy and paste from there. Please ask the instructor for help if you get stuck this is NOT a test.
When we are done, submit work before the next class. If you cannot submit by this time, try to do so as soon as possible after class. Copy this lab with your answers and paste your into the Laulima assignment submission box to Laulima Assignments. If you do not submit something to Laulima you will not get credit.
IMPORTANT NOTE: Starting with this exercise and for all subsequent homework exercises, assignments, and exams we will expect the code that you hand in to be properly commented, to use meaningful variable names, and to use proper indentation!!!! This is a very good habit to get into.
a. Name three functions that we have used in class thus far and give an example of how each of them may be used. Note that conditionals such as while()
and if()
are not functions.
1)
2)
3)
b. For your example function (1) above, in the browser console or using node -i
, just type the function name and explain what output you get and why. Assign the function to the variable xxx
and show how you would use this variable in your example for (1) rather than the function name. Why does this work and explain what the ()
operator does.
a. (5 minutes) Define the variable attributes = "<name>;<age>;<major>"
. Using W3 schools find and read the documentation for an appropriate function that might be used to cut up a string into an array of parts that were separated by a given character in that string. e.g. “a;b;c” would give an array of parts [“a”,”b”,”c”] if asked to separate by “;”. Give an example of calling this function and the resulting output if any to get the name, age, and major substrings in attributes
:
b. (3 minutes) How many parameters does this function take? How do you know what the parameters are and what values they expect? Is it necessary to place the parameters in a certain order? Why/why not?
c. (4 minutes) What parameters are required? What are optional? How did you know? Give an example of using an optional parameter for this function.
d. (2 minutes) Is the function named appropriately? Explain why or why not.
e. (5 minutes) Explain why it is not necessary to give the string in attributes
as a parameter to the function. How does this work and why this is better than putting the string directly in the function call. Why is this different than parseInt()
where you do have to put the string in as an argument?
attributes = "<name>;<age>;<age + 0.5>;<0.5 - age>" ;
Use the function you found in (2) and assign the return value to pieces
and use this and a loop to print out the parts you get when separating by “;” and the data type of each part (use typeof
).
a. (5 minutes) Use typeof
to find out what data type pieces
is. Explain where the value stored in pieces
came from. Explain why the data type of pieces
is different than the data type of the parts in attributes
. What problem might you have if you try to use these parts as the data types they are intended to be?
b. (5 minutes) Lookup (or guess) a function that would “invert” pieces
back into a string. Use this function to invert the array pieces
into a string of the elements separated with “,” rather than “;”.
a. (4 minutes) One of the challenges with splitting a string into parts is that the parts will be strings. This kind of thing happens frequently and if those parts are intended to be other data types we will have to check (“validate”) that they are the data type intended.
Put the following code into a function called isNonNegInt
that takes a string parameter q
and validates that the value of this string is a non-negative integer.
errors = []; // assume no errors at first
if(Number(q) != q) errors.push('Not a number!'); // Check if string is a number value
if(q < 0) errors.push('Negative value!'); // Check if it is non-negative
if(parseInt(q) != q) errors.push('Not an integer!'); // Check that it is an integer
This code will collect any validation errors in the errors
array. Have the function return true
if after checking everything the array is empty and false
if not (Hint: use the expression (errors.length == 0)
). Write a loop to test this function using the pieces
array. This program should be very short, about 5 lines, if you have defined the function properly. Be sure you know the difference between defining a function and using it.
b. Add an optional boolean parameter returnErrors
that when true
returns the array of all the errors rather than a boolean. Rewrite your test to use this and have the same output. Hint: use the ternary expression returnErrors ? errors : (errors.length == 0)
. Why is it better to return an array rather than just a boolean?
c. Following good function naming conventions, rename the function you created in (a) and explain briefly why it is or is not an appropriate name that follows the conventions. Rename the parameter and add comments to the top of the function that explains what the function does and how to use it.
d. (3 minutes) You need to check that the quantities of 10 kinds of products the user selected in your store are valid. Explain the benefit of creating and using the function you created rather than repeating the code to do the validation 10 times.
Define the following functions in the console or node -i
:
function junk1() {
for(i1=1; i1<=2; i1++){console.log(i1);}
return `i1 is ${i1}`;
}
function junk2() {
for(var i2=1; i2<=2; i2++){console.log(i2);}
return `i2 is ${i2}`;
}
function junk3() {
for(let i3=1; i3<=2; i3++){console.log(i3);}
return `i3 is ${i3}`;
}
a. Execute junk1()
then i1
explain why i1
is defined outside the function.
b. Execute junk2()
then i2
explain why you get Uncaught ReferenceError: i2 is not defined
when you try to use i2
outside the function.
c. Execute junk3()
then i3
explain why you get Uncaught ReferenceError: i3 is not defined
for each of these and why the return value i3 is 3
does not appear as it does for the previous examples (that is, you cannot use i3
outside the function or outside the for-loop).
A callback function is when you give a function as a parameter to a function call. The idea here is that the function being called will use (invoke) this function inside itself to perform some action or routine and then “call back” to the caller when it’s done (although in some situations this is not done). In Javascript functions are “asynchronous” meaning that when they are called they execute in a separate “thread” which runs at the same time as the thread that called the function. This means that the function does not have to complete executing its code before continuing to execute code after the function is called. This is both useful and troublesome. Useful since you can execute multiple things at the same time (in parallel). Troublesome in that you cannot rely on using the result of a function call in subsequent code (or in other functions). A callback function is useful here, particularly in Javascript, for addressing these issues:
document.onload = "function doStuff(){ ... }"
Define a function checkIt
with 1st parameter item
and 2nd parameter index
console.log(`part ${index} is ${(isNonNegInt(item)?'a':'not a')} quantity`);
a. Use checkIt
as a callback function in the .forEeach()
method for the array pieces
you defined in Exercise 3. Put your code and output here:
b. Do the same as above but define an anonymous function for the callback directly in the .forEeach()
. Start with pieces.forEeach((item,index) => {} )
then copy the code block for checkIt
and paste it inside the {}
. Do not add an additional {}
. NOTE: this is very simple. There is not much to do here. Explain the benefit of using an anonymous function rather than defining checkIt
in this example:
c. [using callback to deal with asynchronous operation] Asynchronicity means that if JavaScript has to wait for an operation to complete, it will execute the rest of the code while waiting. JavaScript is a single-threaded programming language. It carries asynchronous operations via the callback queue and event loop. Let’s look at how this works and how it affects how you write your code. Suppose that you need to develop a script that downloads a picture from a remote server and process it after the download completes. Copy the code below which simulates this:
function download(url) {
setTimeout(() => {
// script to download the picture here
console.log(`Downloading ${url} ...`);
picture_data = "image data:XOXOXO";
return picture_data;
}, 3* 1000);
}
function process(picture) {
console.log(`Processing ${picture}`);
}
let url = 'https://www.example.comt/big_pic.jpg';
process( download(url) );
Run this code and explain why it tries to process the image before downloading it and why picture
is undefined:
Now add callback
as a second parameter to download
then replace return picture_data;
with callback(picture_data);
Change process( download(url) );
to download(url, process);
(note that we are passing the fucntion process
as the callBack
paramater to download
). Now check that the image now processes after the download as desired.
Create a function that takes an array of numbers, called monthly_sales
(a list of monthly sales amounts), and a tax rate (tax_rate
) as inputs. The function must return an array called tax_owing
, which consists of one entry for every entry in monthly_sales
indicating the tax owing for that entry.