[ Silence ]
>> Welcome to Section 4 S-75.
This is July 18th, Wednesday evening.
We're going to be talking about JavaScript this evening
and about JQuery and about the document object model.
So, as always with my sections,
my name is Myer [assumed spelling]
and I'm one of the TFs for S-75.
You can find the code that I talk through tonight
at github.com/codekiln/S75-Sections
and if you just go to that URL and then scroll
down their instructions on how to view the code
in the CS50 Appliance so that it appears for you
like it does for me right here.
This is the CS50 Appliance over to the right.
So first since we're at this page, I'd like to point
out a few new links for this week.
I've put in some links to some JavaScript videos
by Douglas Crockford.
Each one of this is about an hour long,
so you probably don't have enough time
to watch it before next week but all of these are great.
I have a bit here about JSLint specifically
about how to install it.
David talked about that at the end of class and we're going
to go through a little bit of that this evening as well.
Finally, there are some links
to JavaScript documentation generation in the spirit
of JavaDoc or like PHPs documentation
generation capabilities.
And finally, there's a link to JSFiddle which a great place
to test JavaScript online.
Up in the left hand quadrant here you see the HTML
that the JavaScript operates on and here
in the lower left quadrant you see the JavaScript
that you are able to do.
In the upper right quadrant you are able to enter in CSS
and then the result appears in the lower right hand window.
And you can even link to your specific example with JSFiddle.
So, I highly encourage you to mess around with JSFiddle
when you're thinking about a user interface prototype
for one of your assignments.
Maybe you can mock it up here
and then once the interface details are kind of flashed out,
you can move it into production mode.
So this evening we'll be working
through the July 18th code, which is right here.
So I'm going to change directories into July 18th
and let me just get it up here.
So tonight, the first example I wanted to run
through is a quick example of how to make PHP recourse
through the directory tree beneath the directory
that the file that houses a certain PHP code is and print
out the results of the directory tree.
In a sense, that's what Apache does
for us right here except they don't expand the sub
nodes automatically.
You actually have to go to another page in order
to get the listings of the subdirectory.
So here's our first example,
you'll see I've structured the folders a little bit differently
because in our assignments we're now putting the index.php,
that is the point of entry into the application,
in the HTML directory and so we have to step
into the HTML directory in order to see the result.
So when we step in, you can see that these are all the files
that are inside of the folders, private PHP and HTML.
If I go back and go into private underscore PHP you'll see those
files available.
So, I did this structure in order to give a simple example
of what David was talking about.
David mentioned that we want one directory that houses all
of the public facing files.
All of the files that are chmoded 644 world readable
and then the single index.php that's the entry point
into your application and then from there including all
of the other business logic that is stored
in a separate folder that--
maintaining that separation makes it easier to make sure
that your business logic, which is private to you and private
to the business you're representing if you happen
to be working for a client,
making sure that that business information is actually kept
private in case you flip one line of code in httpd.com
or php.ini that actually spits out all the PHP to the screen
as text rather than processing it.
So, if I use the tree command, I'm not sure--
yeah, it's installed here.
You can see the directory structure mimicked
like how it is here.
This tree command is kind of the inspiration
for this little application.
If I step inside html/index.php you'll see
that I basically set some constants
and then include the controller.
[ Typing ]
And the controller calls the model,
sets a few configuration variables
and then calls the view.
So let's just take a look at the view
or actually let's take a look at the model.
Inside model.php is two functions, php file tree
and php file tree dir. And both
of these functions are the functions that recourse
through the subdirectories and generate the HTML
that is seen here if I do view page sort or a view page source.
The way that it generates an unordered list with a list item
and then a link and then it closes the unordered list
for HTML.
All of that HTML is generated inside this function
and it calls itself recursively.
I'm not going to walk through these
because we have a lot JavaScript to get through tonight
but this is an example of some business logic
that would be private from the client that is kept
in a separate folder from the point of entry
into your application.
So this is how it looks without JavaScript.
And the next version, we'll add some JavaScript
so that it only shows the directories
and then we'll be able to click into those directories
and just see the files.
So let me--
[ Typing ]
-- go into 01.
We'll go into 01 in here as well.
If we go on to the HTML directory,
now we see an HTML folder in a private underscore PHP folder
and if we click that it expands and if we go
into the HTML directory, this is the directory that's supposed
to house of the world readable files.
So we see we have a JavaScript folder.
If I have styling in here,
I would put it inside the CSS folder.
If I had images, I would put it inside an image folder inside
this public folder.
I am going to change directory into JavaScript
and look at main.js and--
[ Typing ]
And inside the view I echo out the directory
that the JavaScript is kept in and this is the style
for including a JavaScript.
David probably went over this in the lecture.
You say script and then SRC equals and then the URL
to the JavaScript file.
The JavaScript file has to be chmoded 604 at least so that
that last byte has that world readable permission.
And for legacy reasons, we don't self-close this tag.
Instead we close the script tag
and then put a closing tag after it.
That just ensures that it loads.
And we know that this is loading
because this functionality is here.
So let's take a look at the JavaScript.
[ Typing ]
So we have one function, init php file tree
and that function spans pretty much the entire document
and then down at the bottom we have window.onload = init php
file tree.
So in this file, what we do is generate a function
or declare a function and then set that function to be executed
when the windows.onload handler files.
So this evening we're going to talk
about the document object model.
The document object model is a model inside the browser
of the page's content and the content
of the document object model, you can think of it
in your head like the HTML file.
It's a hierarchy of parent-child nodes and it really just--
in the document object model, the HTML content is an object
and the body section is another object and then each one
of these objects has properties
and the properties include placeholders for events
to happen and one of the most important document objects is
the window object, which is JavaScript's representation
of the window that houses the web page and that window
like many of these elements has an onload property
that you are able to set equal to a function
and if you set it equal to a function,
then when the onload event occurs, in this case,
when the window is loaded then whatever function is stored
inside that onload property will be executed.
And it's up to the browser manufacturer to make sure
that that function, the onload function is--
the function stored in the onload property is called
at the right time and you would have to look
at the documentation of the DOM in order to find
out what those properties are.
Some other properties
that various elements have are onclick
and if you store a function inside an onclick property
of the document object such as an A element then you can have
that function executed when that A element is clicked.
So if we go into this just a little bit more,
we can see our second document object,
this is the global document object, which is the object
that represents the entire HTML document
and it has a function getElementsByTagName.
What that function does is make it so that you can get a list,
technically an array of all of the list item elements.
So what this is finding here is all
of the li elements as an array.
So now aMenus, the variable, has all of the list item elements
and you will recall that we encoded all
of these files as list items.
So when we get all of the elements by tag name
for list items, it's getting this item
and this item and this item.
If we press ctrl shift C in Chrome,
you can see that this is a list item and this is a list item
and now inside aMenus is an array
of the document objects representing this node
and this node and this node and this node.
And every array has a property called length
and you can iterate through it and you--
Another property that document objects have is the
className property.
The className property contains all of the class names.
You'll see in here, here's a list item
that has an attribute class = pft-file
and also a class name equal to ext-php.
So in this line, we can retrieve an array of all of the classes
for the document object and if the class begins
with pft directory, and this is something that's leveraging off
of what the PHP function does.
It creates a UL-- it creates an li element
that is annotated PFT directory
if it is the name of the directory.
So that logic-- that data is encoded here into the HTML
and we're able to extract that data with this statement.
The index of command is a function that returns the index
of a substring inside another string.
So for instance, in the word string--
substring, index of string would be zero, 1, 2,
3 because this substring appears here starting at character three
and it returns negative one
if the substring is not found in the string.
So what this is detecting is the following logic will only be
executed if the class name begins with the directory.
So now we're going to handle the directory and in the directory,
we will get the child nodes.
Here's another document object property.
The child nodes document object property contains a reference
to an array that contains all
of the child nodes of the current node.
So in this case, actually it would be easier on the screen,
if you look here at the screen.
List item class equals PFT directory, that is what--
inside this list item, the list item class equals PFT directory
is aMenus underscore i and we're going to get the child nodes
of this and as you can see how it indents,
it's going to return an array of references to all
of its direct children.
And again, arrays have a length property.
So you're able to iterate
through until the end of the array.
So when you're getting to know JavaScript and getting
to know the document object, you'll pick up a few
of these property names along the way,
and then once you've learned a few you'll have a good handle
on what API the document object model exposes to you.
Here we get all of the sub menus
with tag name equals A. Tag name is the actual name
of the element, so here is an A element, an anchor element,
and so now we're going to handle this anchor element
and set the onclick property of that equal to a function.
Now here is JavaScript we have an anonymous function.
The function is declared right here inside the loop,
you have function and that function goes all the way
to here.
Let me highlight it.
That's the entire function
that is then stored inside the onclick of the sub menu.
And because in JavaScript functions are first class
citizens there are-- functions are first class data
in JavaScript, which means that they can be passed
into a function, return from a function,
in here we're storing a function inside of a variable
and that variable is a property
of whatever object is inside the array submenu[j].
So sub menu is a an array of objects.
We have one of those objects currently in memory
and we're putting inside a property
of that object a function that would be executed
at a particular time that is arranged by the browser
and onclick happens when you click on it.
And-- so I'm not going to go through all of the code line
by line but basically, what that does is make it so that
when you click on the files themselves it gives you an alert
that actually tells you the name of the file itself.
Inside each of these document objects,
in this case it's an anchor object,
there is an onclick property and inside each
of those onclick properties this is a reference to this function.
So I think we've kind of established the basic point here
so let's retreat out a little bit.
So, when you're writing JavaScript, it's important
to be stylistically consistent.
JavaScript is a language that was made in a hurry,
it was made in a very short period
of time during browser wars between Netscape
and Internet Explorer.
And the browsers were trying to one up each other
and it was developed during a very short period of time.
And so as a result there are lot of good things in JavaScript
but there are also a lot of bad things,
and the bad things are not useless but there are things
that lead to dirty code.
So at the beginning of the section I talked
about these videos by Douglas Crockford.
He is a JavaScript guru that was around at the time
that JavaScript was first blossoming onto the stage
and he was one of the early players in that space.
And Douglas Crockford is I guess most famous
for having invented and-- one could say maybe not invented
but popularized the JSON JavaScript object notation data
format that we're going to use later in this course.
And Douglas Crocfkford is somebody whose program did a lot
of languages and he understands a lot about the interaction
between coding style and a predisposition for errors
to creep into the code.
And with that in mind he wrote this tool originally
as a stylistic enforcer for writing good JavaScript code
that would teach you and enforce
in your own code these certain best practices
with the JavaScript.
Stuff that's written with JSLint doesn't necessarily run faster,
it's just cleaner, easier to maintain and in general, more--
it tends to reduce the probability
that bugs are difficult to see for predictable reasons.
So its most often used online
because it's a tool that's written in JavaScript.
You can paste some JavaScript right
into here and then lint it.
In fact, if we go back into JavaScript and--
let's see of it opens up.
So you copy it and here press JSLint then you'll see a list
of all the stylistic things that you could have done differently
but I highly encourage you to re-factor your code with this
in order to learn from Douglas Crockford's experience.
He is very idiosyncratic and he has a certain way
that he likes things coded
and that way is not necessarily the best way
but he is somebody certainly who has a lot of experience
in the space and it can't hurt a JavaScript developer to know
about Douglas Crockford's highly influential style in the space.
So you can certainly correct it here in the browser
by pasting it into this display and then clicking JSLint
or you can integrate it into your actual command line here.
I've included some instructions here
for installing it in the Impliance.
Once you install it
in the appliance then you can do a jslint main.js
and it gives you those same errors
that are right here at the command line.
And because it's in such a predictable format
and because people have been writing code on the command line
for years, there is a syntax called error format that is used
to help parse the output of thees linters.
A linter is a tool that helps you analyze your code and see
if you can improve certain things about it
and it goes all the way back to C, there were linters for C.
And in this case if you know the error format you can write a
little script for Vim, the editor, that will read
through the document and let you process it all in one place.
So I'm going to copy main to main2.js and just open up that
and because I have error format installed, I can press F4
and you can see it jumps to the first error which is
on line 33 column 3 so I can go 33 capital G and then go
to column 3, right here.
It puts your cursor right there and it says missing use
of use strict statement.
So at this point if I was curios about what
that meant I could say use strict JSLint
and usually a Stack Overflow thing comes up
and see 619 people have found this useful.
And so basically, you have to put
that phrase use strict somewhere in your code and you can read
through here in order to figure out why the basic answer is
that there are many different versions of JavaScript
and for backwards compatibility reasons
when they made new versions of JavaScript, they didn't want
to deprecate certain features that were a bad idea
because it would break the code.
So if you do use script
or use strict then it deprecates certain things
and makes available ceratin things.
And so let's go up here to the top and just put use strict
and now I'm going to press F4 again.
And that error has gone away
and now we've moved on to the next one.
It says, expected if at column 5 not column 5, oh,
well E wants us to indent in a certain way, so I'm going
to make it go now, you can see right here, I'm at column 5,
not column 3, press F4 again,
and it says document was used before it was defined,
so again you could Google this,
document used before defined JSLint.
In general, when you have a global variable,
global variables are very, very problematic in JavaScript
because on one page, you can have not only the page authors
JavaScript code array but maybe an ad running
that is loaded dynamically
through a content distribution network where the person
who wrote the JavaScript doesn't even know what page it's running
on and because there is the capability for global variables
to exist in JavaScript, if you make an--
a variable called foo in your JS file and then
in an ad.js file they, unbeknownst to you,
also make a var foo then which ever one is located lower
on the page when it's actually loaded will clover the earlier
version of the variable.
So this is very problematic in JavaScript.
It's one of the not the good parts of JavaScript but one
of the bad parts and to mitigate that, he wants us to acknowledge
in the code that this is a global variable by putting
in this global directive.
Basically, what he's suggesting here is
that every single global variable you should acknowledge
that it is global and that it could be--
it could be clobbered.
So, if I press F4 again, it says, document, let me see.
Oh, yeah, you have to say global document,
and it says document was used before was it defined
so if I do var document then, now, we can go on.
It says expected a left brace and instead saw a return,
so here he's saying you need to insert a right brace
and basically, what he's suggesting is
that it's bad coding practice, do not use these braces with ifs
because it lets bugs go into your code more easily.
So, now it says, expected var at column 5 not column 3,
I'll make it go to column 5, combine this
with previous var statement.
So, in JavaScript you can declare all your variables
at once and then we're going to get-- it's--
the for is expected at column 5, so basically they want 1, 2, 3,
4 spaces for each indent and you can guess that this variable
and this variable as well are also going to come up.
We're going to need to insert I, M class,
all of our variables here at the top.
So, if you move all the way out and complete the cycle.
[ Typing ]
If I press F4 here, you can see it just returns.
I'm completed with linting this and I've--
You can see that all the variables are defined
at the top of the function.
Here's a global document directive
for the global document object.
Here's another function and this one is pretty different,
this is a pretty significant departure
from the previous version.
Let me just open that one up side by side.
[ Typing ]
So, before you'll note that we looped through
and inside the loop, we declared an anonymous function
that was put inside the onclick handler for, here it is, yeah.
submenu[j].tagName = A then submenu[j].onclick = function.
And then here's this huge function.
Well, this is very problematic and it leads to bugs,
especially with event handling,
because we're storing separate function in every single element
of that array even when JavaScript has the ability
to store a function in an object like this,
submenuOnclickFunc = function.
And then here is that same code.
It goes all the way down to there.
And now, we began looping through.
And now, it's reduced to one line,
submenu[j].onclick = submenuOnclicklFunc.
And not only does it make more readable like you'll notice
that here it has to indent quite far in order to get
through all that nested logic.
But also it makes it, more importantly,
it makes it more correct because when you're dealing
with event handling functions, it's very important
that you're only dealing with one function in memory
and not creating a thousand functions.
Each function has an instantiation cost
so if you instantiate a thousand functions you have
to do that each time.
Also, there's no predictability about events.
I could get into exotic examples that have to do
with timed delays and maybe with things moving around
but you'll have to take my word for it or watch his videos
because he gives a good example of it as well.
So, this is, in general, the way that he wants you
to do it and it's a good idea.
Declare all your variables at the top of the function.
Then-- And then initialize each of your variables.
Here one of our variables is a function that needs
to be initialized with this function.
And then go into the logic of the function itself.
So at this point, I want to take a step back.
And just run you through some slides from a presentation
that Crockford made a few years ago.
This is for YUI Theater.
So we're just going to run through the quick syntax
and some of the pitfalls and some
of the examples of JavaScript.
Again, this is by Douglas Crockford.
These are his slides.
He gets into a lot of really kind of esoteric examples
that we will not get into here but these are some, you know,
some bridge selections from some slides that he's done before.
So, JavaScript has good parts.
We'll get to them later.
Right now, we're going to kind of talk about the bad parts
which come from legacy, good intention and haste.
Haste because it was developed really fast.
And so with numbers, there's no integer types so immediately
with the integer type--
if you're dealing things with money, you'll have to be aware
that there's going to be some rounding
because there's floating point math all over the place.
Of course, it is 64-bit floating points
so you can achieve a level of precision with it.
But everything is based off of approximations.
And that becomes problematic in certain points.
For example, the associative law does not hold
because of the slight bits of rounding that happen
with the floating point representations of the numbers.
So this actually produces false for some numbers of a, b,
c even though mathematically it's not a false statement.
So, decimal functions are approximate.
That is actually false here.
In JavaScript there is a math object and when we talk
about objects in JavaScript we use dot notation in order
to access the member methods.
So in here you would do math.sqrt and then pass
in parameters in order to get to the square root function.
So be aware that if you want to use any of these functions,
you have to prefix it with that math object names
for the global variable and then the dot operator.
And again, this is, you know,
an example of how fragile the global name space is if some,
you know, malicious JS were to override the math variable
and replace it with its own contents.
Maybe they could even manipulate your code if they knew
that you were using and relying on those functions.
So that's an example of how to call a math function.
NaN, you'll see this inside of your debugging.
This is-- this stands for Not a Number and it's the result
of erroneous operations.
So if you do a 1 divided by 0, then you'll get NaN.
The-- it's toxic so any arithmetic operation with--
that produces this result will also have NaN as a result.
So that means that if you add 1 to 1 divided
by 0 then the result of that will also be NaN, not a number.
But here are some other bad parts.
NaN is not equals equals equals NaN which is very strange
and even stranger, not a number is not equals equals NaN.
So the difference here between equals equals equals
and equals equals is that the first does not involve type
coercion, it's strictly quality.
But the second does allow type coercion
and by type coercion I mean that you can
in certain cases treat strings like numbers
and in other cases you can treat them as strings.
And we'll get into that a little bit later on.
So in order to test equality
with strings use equals equals equals plus can mean concatenate
two strings or it can mean add.
So here the string dollar sign plus the string 1 plus the
string 2 equals the string dollar sign 1, 2.
And it's equivalent to using the concat function.
And here you'll see this string that's contained in these--
between these two singles quotes that is actually accessible
as an object using the dot notation.
And it has the concat function as a method of that object.
Everything in functions or everything in object--
JavaScript is an object/function.
So in order to convert a number to a string,
you can call toString on the number
because numbers are objects.
There's this interesting operator, the plus,
if you put plus in front of the string one like plus 1,
then that actually turns this into the number one or if,
sorry, if var contain-- if a variable contains a string
and it's used with the plus operator, then you can coerce it
into a number by using typecasting facilities.
You can also use the parseInt, the global parseInt function,
where you pass in a string, and then you specify the--
you specify the radix.
Every string has a length property,
this is much like arrays.
Arrays have a length property as well.
This contains a number that's equivalent
to the length of the string.
Extended characters are counted as two, so that means
that if you have a Unicode character like umlaut u
or something, then that will actually give you a count of two
for one character if it's, you know, a multi-byte character.
So for arrays, arrays inherit from objects,
so arrays are also objects, they also have a length property,
which allows you to look through them as we saw before.
In order to do an array literal, you use the square brackets.
This is much like some other languages.
You have to put commas in between the different items,
and then new items can be appended by doing the--
by including an L-- an index that's outside of the array.
So the thing that's really kind of nefarious about arrays is
that indexes are actually converted to strings and used
as names for retrieving values.
This is really strange.
The-- You can run to some problems with it.
It's not like a Java array or something where if you-- the--
if you remove an index from the middle of the array,
you'll literally have an array with a hole in it
because those are string keys
to those values unlike, say, a Java array.
So array methods have-- these are some array methods,
and because these belong to the array object,
you can have an array and a variable
and then just call dot splice or dot slice or dot sort.
So sort is very unusual because it defaults
to alphabetical ordering.
And in alphabetical ordering,
this is actually the alphabetical ordering
of these numbers, so be aware, and even if you put numbers in
and you call sort, then they'll sort
out of order unless you actually, you know, do sort
and then pass in this function
that returns a number that's either greater than zero,
equal to zero, less than zero in order to indicate
which is greater than which.
So that's part of the bad elements I guess
of JavaScript, the funky defaults.
Here if you do delete--
delete is a keyword and if you say delete array and then three,
in an array that's five indices long, then now you have a hole
in the numbering and if you try to loop through it,
you'll actually encounter an error at that point.
But array.splice will remove the element
or renumber all the following elements,
which is pretty inefficient.
So use objects when the names are arbitrary strings
and use arrays when the names are sequential integers.
They're very similar in JavaScript.
In JavaScript, the simplest object is two curly braces,
in JavaScript the simplest array is two square braces.
And you can have objects that contain arrays,
and you can have arrays that contain objects, as we'll see
when we get into JSON in a little bit.
Unlike a lot of languages, regular expressions,
which is a special sub-language that's designed
for searching strings, they're actually a type in JavaScript,
and you actually indicate them with the slash on the end
and the slash on the beginning.
So you can literally say var foo equals slash star dot-- or dot--
or, no, php dot star slash and then semicolon.
You don't have to put in strings like some other languages.
So in JavaScript things aren't typeless,
everything is loosely typed.
But all of these values are kind of falsy.
And so if you put each of these things inside of an
if statement, it will not execute.
And so these operators are equals and not equals.
And they can do type coercion,
which means that they can convert strings into numbers
or vice versa based off of what JavaScript thinks is best.
You can learn those intricate rules
of when the type coercion happens or you can do
like Douglas Crockford suggests and just use these all the time
which do not use type coercion.
And the reason why you should do that is because type coercion
and JavaScript is evil because here is an empty string, == 0,
that is false, but the number 0 zero == empty string is true,
and even worse, the number 0 == the string 0 is also true.
So this is totally bizarre.
Type coercion is truly pretty weird and I ask you
to please stay away from it
by using the non-type coercing operators.
So all values in JavaScript are objects except
for null and undefined.
Null is a value that isn't anything.
And undefined is a value that isn't even anything.
All right.
It's so weird that they have both of these keywords,
and it has to do with this structure of variable hoisting
that happens in JavaScript.
And undefined is basically the default values for all variables
and parameters that haven't been assigned a value.
And it's in fact a value of missing members and objects.
So if I have, you know, var M equals the simplest object
and then I want to access M.foo
which hasn't been accessed-- declared yet.
This is undefined at that moment, which is different
than null because null is something that-- It's like--
funny to think of it this way,
but it's actually a positive statement.
It's saying, "This is not anything."
And undefined just means it hasn't been defined yet.
So I put this in because JavaScript also has a switch,
a switch statement.
So that's most of the bad parts.
Getting on to functions.
There are two ways of declaring functions in JavaScript.
The-- There are function statements
and function expressions.
This describes function expressions.
This little part right here is a function expression.
This is what we saw before
and when we declared a function anonymously
and inserted it inside the onclick handler
of that A element.
Function expressions have the function keyword followed
by an optional name and then, you know, maybe some parameters
like x here is passed in as a parameter.
Note that you don't have to do var x or string x,
there's no type checking that's done,
so you just name whatever variables you want to pass in.
And then the body has to be wrapped in curly braces
and contains zero or more statements.
That's a function expression.
A function expression produces an instance
of a function object.
So the result of this is that an instance
of a function object is inserted into this variable at one.
Function objects are first class,
which means that they can be passed
as an argument into a function.
They can be returned from a function, they can be assigned
to a variable like we did here, we assigned the function into--
to be stored inside that variable
and it can be stored inside an object or array.
That's what it means to be a first class entity
in computer science.
A function statement on the other hand is like this.
So you have the function keyword and then you have this label
for the function and these are something that you can do,
but it's a little bit deceptive and Crockford recommends
that you actually kind of move away from this
and go more toward the expression syntax.
And the reason why is because function foo,
with no parameters, an empty body,
expands to variable foo equals function foo
with no parameters, no body.
And this in itself expands to variable foo equals undefined
and then foo equals function foo.
So this is really just a long complicated way
of performing a function expression
like why didn't you just make a variable foo
and store an anonymous function in it.
It's a little bit deceptive to do it this way
and it's really some syntactic sugar to help persuade people
who use classical languages just like Java
or C++ to, to use JavaScript.
So when they say the assignment of the function is hoisted,
this is one of the most misunderstood things
about JavaScript and it's-- it can--
it'll really trick you up in your assignments
if you're not aware of it going into it.
Be aware that when you start to get some bugs that have to do
with variables being assigned values
and you don't understand why because it's inconsistent
with PHP and C++ and Java and other languages
that you've used, it's because in JavaScript we have function
scope and not block scope.
So here I just want to reinforce this one
where you put an anonymous function inside a variable,
that's a function expression.
Here where you say function addOne this is the
function statement.
This is the one I don't want you to use.
This is the one I do want you to use.
So a var statement declares
and initializes a variable within a function.
A variable declared anywhere
within a function is visible everywhere within the function.
This is the thing that really tricks people up that come
from other languages because if you have var x equals function
and you have some code here,
var x var y equals 2, var x equals 3.
Var-- even though there's code here x is actually available
inside this code because what happens behind the scenes is
that this part moves all the way up to the beginning
of the function and there's implicitly this var x,
y and then you're left with y equals 2 and x equals 3
and X is actually valid
as a variable inside all the entire body of the function
and that includes functions that are nested within functions.
So that's why Crockford recommends you declare all
of the variables from the function right at the top
because technically, that's what happens behind the scenes
so why not make it more clear.
So declaring a var, it just expands it
out into two declarations where my var equals undefined
and my other var equals undefined
and then the initialization happens.
So this function would work in Java, it would work in PHP,
but in JavaScript it doesn't work because what happens is
that there's not a new variable i here.
There's only one variable i and it's hoisted up
and declared right here and set to undefined
and then it's overwritten.
It'll let this-- this program will run forever.
It will not terminate because i is not really declared here.
So that's why you should always hoist your variables, you know,
as a preventative measure.
So declare all your variables at the top of the function
and declare all functions before you call them.
The language provides mechanisms that allow you
to ignore this advice, but they are problematic.
So this is also problematic
so if you leave off a semicolon JavaScript will actually insert
it for you automatically.
If you are to leave a semicolon off here,
JavaScript will be like, oh he meant semicolon,
and semicolon means that that's the end of the statement.
Unfortunately, the semicolon isn't always inserted
in the right place and it isn't--
doesn't exactly do you want so you have
to be really careful not to admit those semicolons.
So besides variable hoisting the value
of the this variable is probably the single most confusing thing
about JavaScript.
So this parameter contains a reference
to the objects of invocation.
What that means is that the object
when it's actually invoked, when it's actually ran
in the browser, this is--
the keyword this is very different depending
on where it is instantiated.
So in general this allows a method
to know what object it is concerned with.
And it allows a single function to serve as many functions.
You know, it is really important.
It's the key to making big structures.
Things like Gmail wouldn't be possible without this keyword.
As we saw at the very end of lecture the parentheses,
suffix operators surrounding zero
or more comma separator arguments will invocate whatever
comes before it.
And by invocate we mean execute.
If a function is called with too many arguments the extra
arguments are just thrown out.
If a function is called with too few arguments the missing values
will be centrally undefined because everything is set
to undefined until it's a set of value in JavaScript.
And there is no implicit type checking of the arguments
like there is in Java.
So there are few-- there are four ways to call a function.
There's the function form where you have an actual function
that you're evoking like-- let's say-- what's a good example.
Well like any function that you define
on your own in global scope.
And there's the method form
where you're actually calling it as--
it's called a method rather than a function
because a method refers to an object that opens it
or that it belongs to.
A method is a function that has references to properties
and variables that situate its context.
So this is actually the most common names.
So like math.sqrt is the method form.
When this function--
when a function is called
in the method form this is set to that big object.
So inside the body of this function, of this keyword,
it stands for the math object inside math.sqrt.
And this allows methods to have a reference to the object
of interest which is important
because in the math object they might have lots of constants.
They might have a constant called pi.
In the function form the-- you--
like we thought anonymous functions then you have--
well, some anonymous functions.
This keyword is actually set to the global object.
And if you make-- a function is nested
within a function then the inner function will actually have its
own scope and its own this keyword.
And so in order to get access
to the outer functions variables you need to set--
in the outer function you need to set a variable
that traps this variable and make it available.
So let me explain what I mean.
If you have--
[ Writing on Board ]
Var outer = function.
[ Writing on Board ]
Var secret = 12345.
Var--
[ Writing on Board ]
So in-- actually this is.
Let's say that the-- that this was--
let's say that we're talking
about the onclick handler before.
a.onclick equals function x. This element here contains a
reference to that A document object in this scope.
However, here this variable contains a reference
to this function.
So in order to get access to the A document object you need
to say var that = this and then inside here you can say
that.classNames, you know, you can perform operations
on that anchor document object inside of this function
by making sure that this local scope doesn't clobber this
variable, this keyword that you need access to.
So this chart is really the key to understanding it.
If it's called like math.sqrt then inside
that this object contains a reference to the math object.
If it's called in a function format
like where you just call the name
of the function then this actually contains a reference
to the global object or it's undefined depending
on the version of the JavaScript.
If you instantiate a function using the new keyword then you
actually get inside this object the new object.
And we won't talk about apply.
But this can actually change a lot about the way
that JavaScript is done.
So let me just say a thing about closure
and then we'll talk jQuery really fast.
So the context of an inner function includes the scope
of the outer function.
In this function that's inner you are also inside the scope
of the outer.
So if we had a var foo here you'd be able
to reference foo inside this function.
The inner function enjoys that context even
after the parent functions have returned.
So that means that if this function is executed,
let's say the onclick happens but do something as a function
that occurs much later, much, much after the onclick event.
Then variables that were in this outer scope are still available
to this function even in that much later timeframe.
And that's key because this function closes
over this function and makes it possible so that even
when a function is like kind of deposed, it's not deposed
but when it goes away and will never be instantiated again.
If there's a function that can be called
within it then you are able to get access to any
of the variables that were declared in the scope around it.
This is the power of JavaScript.
This is like one of the best things about it.
It's a quality that it gets from Lisp.
And if you go through the videos you can see the language
hierarchy and how it derives from Lisp
and other languages with closure.
So here is a way to do a function that uses global scope.
So this is a function that takes a number
and returns the name of the number.
You pass in nine and you get out the string nine.
And names here is accessible inside this function
because you have global scope.
So alert digit name three will actually pronounce the
word three.
So that's global scope.
Here's a way to do that inside a function that's really slow.
You declare function with a large array in it
and then you return the names value and it's slow
because every single time you call the function it allocates
memory for this array, again, which is a waste.
In closure what happens is
that here you see this parenthesis
and this parenthesis.
They're not required but these two parentheses that are
after the function, they are invoking this function
immediately after it's declared.
And he's put these extra parentheses around here.
We're going to call attention
to something special that's going on.
What's happening here is that he makes an anonymous function
and then instantly instantiates it.
And so the function is gone after it's instantiated.
And the result of it being instantiated is
that what's stored inside digit name is a function
and that function itself has access to this variable
that is stored in that scope, that's closed over it.
So this gets declared once in memory and even though
that function has closed
after this variable digit name has been initialized,
even though that function is closed those variables are
accessible to this function that's then stored inside digit
name because it's returned as a first class object.
So this is the special thing about closure.
And it enables you to do things like this.
So here you have a variable dom which stands for an element
that you called getElementById if you know that you have
like div id = 327 then you can say document.getElementById 327
and it will return a reference to this div element in dom,
in the document object model.
And then it also makes a variable level equal to one.
And these are variables that will be available
after this function has been executed.
And inside of this function he makes a function called step
that basically set this function,
setTimeout is something that is available in JavaScript.
You pass in a function and then a number of milliseconds for it
to wait before executing it again.
And it only executes it once.
But here the step function says call me 100 milliseconds later
and level, up here, it's set to 1 and level is incremented by 1.
And it says if level is less
than 15 then execute it100 milliseconds later.
And so h here is set to the string of the level amount.
So it's 1, 2, 3, 4, 5 and it's set in toString
in base 16, I believe.
Yeah, I think it must be in base 16.
And then they're able to actually--
FFFF is for r and g and then the h
and h will actually be the blue code.
And so they're setting the background color of the element
to be an ever lighter and lighter blue value.
It starts out pretty dark and then it gets lighter and lighter
until it becomes FFFF.
And because this level variable is available
to this step function even
after this function has closed then what happens is
that when you call fade id then it will fade really gradually
over, you know, 16 steps to white.
That's the kind of thing that closure let's you do.
So the jQuery is a library that operates on the principle
of that you can store an object inside a variable
with a name that's a single character.
And in jQuery that character is the $, so in jQuery
which is a library that you have
to load any time you put the $ you can then put a dot
and then call a function name
that is built in to that library.
So let's take a look at the jQuery version
of the same PHP directory.
And you can see we have a nice sliding effect.
And it has the same kind of thing
but now it slides up and slides down.
And the sliding facility is probably done with closure just
in the fade manner that we were talking
about using set time out.
So let's take a look at the code.
[ Typing ]
First of all, I'll look at the view.
Oops.
[ Typing ]
So I highly recommend that you are able to go
to the jQuery site and download a file called jquery.js
and then include it in your JavaScript directory
and include it just the same way you'd include your
own JavaScript.
You can do that.
However, there are several advantages to doing it this way.
Google offers as a service--
[ Typing ]
-- these libraries, there are several of them.
It's not just jQuery.
There's Dojo, MooTools, Prototype.
And if you look down at jQuery they give you this nice path.
And if you do the .min.js1, that's the minimized version
so it will be a very small amount of code.
And the advantage to having Google do this is
that there are a number
of servers distributed throughout the country
that Google maintains.
And because JavaScript files are public files you--
and if you hit it once then you hit it again
within the caching period of your browser.
It actually will download it from the closer server
than from the farther server and also, it will download it
onto your own machine if it's from the same domain.
So the idea is that Google is so common and people Google it--
Google things all the time that if everyone uses the same source
for jQuery it will result in faster response time
for everyone and they're very kind to do these things.
It's kind but also they get something out of it too
because they're able to get demographics
about who's using each of the libraries
and make decisions based off of that.
So this is all it takes to include jQuery.
Now let's take a look at the actual script itself.
You can see it's a lot smaller.
This is the entire code required to do the same thing.
Here you'll see the $ object.
Every, you know, every object is a function sort of passing
into the dollar-- the $ variable contains a function
that can be invoked with the parameter.
And if we pass in the document the variable containing the
document object then we'll--
it will return a value that's accessible via a dot operator
here that we'll be able
to actually call a ready function on.
So what this first line does is this gets called only
when the entire document is ready forff JavaScript
to operate on it.
Basically, when the entire document object
of the page has finish flowing
out then it calls this anonymous function inside here.
And one of the notable things about jQuery is
that you can use what's called CSS selectors.
So if you go inside here you'll see PFT directory
and pft file tree or class.
On CSS you select a class with dot and then the name.
So selecting .pHpFileTree selects every object
with the class equal to pHpFileTree.
And then it returns that jQuery object with that array
of document objects inside of it
and because it's a jQuery object that's returned you can continue
to call jQuery methods on it such as find
within that array UL items.
And UL items are like this.
And, you know, if you had a nest--
deep nested structure you'd have more UL items.
And you'd hide them.
So if I restart this that's this very first thing, it hides all
of the subdirectories that are represented by UL elements.
And then it finds all of the A elements that are children
of elements that have a class of PFT directory.
And it registers an event that happens when you click it equal
to this anonymous function.
And this is great.
You can find the parent of the object that is clicked on.
This contains a reference to the object in question.
In this case the document object
that represents the thing clicked on.
So when I click on this,
this variable actually contains the document object model
for that element right there.
And within it, it finds the CSS selector UL colon first is the
very first unordered list.
And jQuery is this nice method, slide toggle
with adjustable speed
that basically unfurls the children elements.
And so jQuery has a great documentation.
You can see that one of the parameters you can pass
in is the duration and another one is callback.
You could pass in a function that it would execute
when the slide is done.
And the slide they're talking about is that slide right there.
And you can even see how it uses overflow equals hit in
and then the height equal to these floating numbers
and it adjusts it, you know, using a millisecond delay
in order to make it look like it's unfurling.
And then like it's sliding open.
And basically if the attribute
of the parent is PFT directory then you return false.
I mean that's the entire functionality.
All of the clicking functionality is put
in there by the PHP actually.
So that's not provided by the jQuery.
jQuery is very, you know,
very easy to get advanced functionality.
And the functioning you're probably using most often
in coming assignments is JSON or AJAX.
JSON is actually an alias to the AJAX method in jQuery.
JavaScript objects notation is--
oh, we just barely didn't get to that slide.
Let's get to it.
So this is the syntax of JavaScript object notation.
You can have brackets and within brackets you can have a value
separated optionally by a comma.
And a value can be a string, number, object,
array, true, false, or null.
And so, you can encapsulate an entire JavaScript object
with this syntax.
And in fact the function parameters here, you know,
they follow this JavaScript object notation itself.
And so, JavaScript object notation is
in data interchange format
and there is a great JSON encode function in PHP
that takes an array or an object like here's an associative array
where the letter A goes to one, the letter B goes
to two, so on and so forth.
And it says JSON encode array and that returns an object
with these curly brackets here.
And you see the string A has a colon
and then value one and then a comma.
And so this is an object with the parameter A equal to 1
or parameter B equal to 2.
Because this function exists and is supported in PHP we're able
to construct an entire data structure
and then call JSON encode and then actually embedded
in our JavaScript, and embedded
in our JavaScript programatically before it is
actually received by the recipient.
And in order to see an example of that--
We'll get into this more next week with AJAX,
but for this week I've included some examples from last year.
Open cycle map, this is just a simple example
where this is a tile from a map
that has a certain name representing its latitude
and a certain or a certain number representing its latitude
and a certain number representing its longitude.
And when you call or when you hit these buttons then
if you're listening on the network you can see
that when you go west it calls the URL with these functions.
You can see zoom equals 15 and x equals 9910 and y equals 1211.
And the result is it returns the directory of--
or it returns the file name of this image.
And the-- you can assemble a very large amount of data
and then actually echo it inside the header of your document
and evaluate it in JavaScript in order to pass that data directly
into JavaScript and be able to access it
with the dot syntax you're used to for the objects.
So that will be more for next week
because it has more to do with AJAX.
But feel free to play around with these examples.
You can see how it goes north and south and east and west.
And each time this downloads it will be impolite
to hit the tile server that serves these up more than once.
So actually what it does is it downloads the appropriate tile,
caches it in a folder on the server and then subsequent hits
to that image are restored from the cache.
So you'll notice if I go north and south and then north
and then north takes a little bit longer.
And now if I go south and north it's nice and fast again that's
because now it's cached on the server.
And this is a style that you'll be using
in the upcoming assignment because you'll have
to be getting certain information about companies
from CS75 finance, caching it on your server and not hitting
that external API more than you need to.
So I thank you for your attention.
This has been a lot of stuff.
I highly encourage you to use JSLint and to watch some
of the Crockford videos.
If you were to just to watch two videos or if you were
to just watch one video, watch Function the Ultimate and skip
through all the parts where it seems
like you're not understanding anyway.
And if you were to watch two videos watch these two.
And they're basically kind of an overview of the syntax,
the good parts, the bad parts,
and what you can do with closure.
So I thank you for your attention and let us know
at the CS50 Discuss if you have any questions.
And if you have any questions about my code in particular,
feel free to email me personally.
[ Silence ]