>> All right, so today, I'm going to be talking
about JavaScript and how it's different from other languages
that you might be used to like PHP.
So in the last lecture on Monday, we talked a bit
about what's similar, what's familiar between JavaScript
and PHP or Python or Ruby or C or other languages
that you're already familiar with.
But JavaScript it actually has a really unique take
on the object model that makes it sort of entirely different
than most languages that you're going to deal with.
So functions are a sort
of underappreciated concept in JavaScript.
They are way more powerful than they are in other languages
because they can in-- for one reason,
they're able to be set as values.
So right here we have var x equals function
and it's a first class value that can be passed
around as an argument.
So you don't have to declare function x
and just use x in that scope.
You can pass the value of x anywhere throughout, you know,
as an argument into another function
where you can module export as David mentioned in node.
So the next point is
that a function is an object in JavaScript.
So you can actually set properties as values
on a function and just treat it like it's an object.
So when you work with jQuery, you know, that dollar
and then you pass a selector into it
and invoke it as a function.
But then you also have dollar dot AJAX.
And that doesn't sort of make sense if you think
of a function just as being something you can invoke
or call.
But JavaScript allows you to set properties on functions
as static properties with just x dot someProp
as I pointed out there.
The next point which we're going to go into a little more
in depth is the fact that functions can be treated
as classes in JavaScript.
So there is the concept of this new operator
which creates a new instance of the function along with a sort
of like class-like body which comes along with it
and we're going to go into it a little more,
it's called the prototype.
And it's what's makes JavaScript very unique compared
to other languages which are class based,
JavaScript is a prototype based.
And then just at the bottom there,
function can just be called plainly as we're used to.
So that's nothing new.
Another thing that's unique is
that arrays are actually objects.
They're not like they are in PHP
where you just create a new array.
This is actually a shorthand for saying new array.
And array is actually a subclass of an object.
So that's something different and I'll go
into a little a more detail on that.
And the debugging capabilities
with JavaScript are really unmatched as far as I've seen.
This is a screenshot of the Chrome Inspector
which we're going to be using for the rest
of the presentation today.
And to get to this, you just go to file developer tools
and open Chrome Inspector or you can right click
and click show element I think it is on HTML page
or I think it's command option J opens this up.
But we'll go into this and you can actually set breakpoints
as you're running through the JavaScript code and sort
of evaluate what the local variables are, what the value
of this is and it makes it way easier to debug code.
And don't-- this is not constrained to browser-side code
but you can actually run a instance
of this Chrome Inspector for your service side code
which is really neat because you can step through line by line
as a request comes into your server and see what's happening
and play with the variables in the console down here.
So as I mentioned, JavaScript is a prototype-based language
which means that there is a set of default values which are sort
of hidden for every function
in the object dot prototype property.
So it's sort of a hash of just different default values
that when you invoke a function with the new keyword,
those are set by default as functions
that are available on the instance.
So that actually is really efficient for the--
it's an efficient way of creating objects memory wise
because the JavaScript runtime only has to keep track
of the prototype of the object.
It sort of points to that
when you cretae a new instance of a class.
And you can also mimic inheritance as is known
in class-based languages where you have sort
of like a this extends that, extends that you can mimic
that in JavaScript through what's called the
prototype chain.
And we'll see examples about that.
So if your-- jQuery plugins actually they recommend jQuery
authors to use dollar dot fn to add functionality
to the jQuery library.
And we're actually going to jump to-- So, on this page,
we have the dollar-- I included jQuery.
And if you do dollar dot in the console
which I mentioned bringing you up through command shift J
or just going to View, Developer, Developer Tools
and going to the Sources tab.
[ Inaudible Remark ]
Oh sure. So when I started to type in a variable,
it's auto-completed for me what is available there.
So I typed in dollar and I can see I think Chrome has some
built-in dollar, dollar and dollar x.
So right now I just want dollar and I put in a dot.
And then it shows me all the properties
that are available on the jQuery object.
But if I do dollar dot prototype,
I now see all the methods that I'm used to using
when I have the dollar, selector and then I chain off that with,
you know, add class or append or blur or any of the like.
Those are all actually on the prototype
which under the hood the jQuery creates a new instance of itself
and it sort of hides all those details from you.
So the point that I was making back over here
with the function, they actually hide prototype from you
and just alias it to dollar dot fn.
So most people actually don't realize
that there is a prototype under the hood that's--
that you can tap into and add additional functionality
to each jQuery instance if you'd like.
So the "new" operator is really sort of difficult
to understand at first.
When you call a function with "new",
it's an entirely different way of calling the function
as if you just called it plainly.
So the "new" operator creates what is called a new instance
of an object or a new instance of, you can think
of the object as a class.
And when this happens, the value of this which may be familiar
with from jQuery, they sort of set this
to whatever is convenient at the time.
They usually set it to the current DOM node that you're
on as you're going through like each or something like that.
They-- This value is supposed to be the value of the instance
that you created with "new", which includes everything
on the prototype chain and all of the methods that you'd find
as prototype properties.
So it depends on how a function is called,
what the value of this is.
And it's really confusing if you're new to JavaScript.
But every function that's called has a-- has at this value.
So even if you haven't created a new instance of something,
that this is assumed to be global.
Or you can call a function using the call method
where the apply method in JavaScript.
You can the function and specify what this should be.
So you can make it dynamic, which is really powerful
but also allows you to do things which can be misleading
and confusing to other developers
if they're not use to the fact.
And jQuery, I would argue makes it even more confusing
by making it convenient and setting it
to the current DOM node.
But the simple rule to remember what the value of this is
when you're looking
at a functional call is what's left of the dot.
So if you have an object
and it's something dot something is the function
that you're calling then the first value is what the value
of this is.
So here is a code example
where I'm creating a new object literal
which is just the object created with the curly braces
and I'm setting name to Bob
and then I have a sayName method here which--
so inside this sayName if I do x dot sayName,
the value of this is equal to x because the left
of the dot is x. So if I call it x dot sayName,
it would say Hello Bob.
And then another example
where I'm actually assigning x dot sayName, the function
to the variable Y, which as I mentioned
in JavaScript you can assign functions
to variables whenever you want, it's really flexible that way,
but now when I call Y, it's lost the context of x.
So this is now global or if you're in strict mode,
I believe it's null or undefined.
But-- So Y is not what you're expecting here if you're looking
at x and you're going to call sayName,
you're expecting this name is supposed to be Bob.
But if you pulled it off the object and called it
by itself, this is now global.
And that's what I was mentioning when you see dollar dot this,
you often don't think of what's actually going on.
But jQuery sort of has their own domain-specific language
for dealing with this and it's not what you're used
to in JavaScript.
And I point this out because it's really important
for writing well-structured object oriented code
in JavaScript to really have a good understanding and grasp
of how this works and how the object model works
and how the new operator works.
Otherwise, you'll end up with jQuery spaghetti
where everything is sort of all over the place
and only dealing with the DOM.
If you can actually write JavaScript
in a more structured fashion, it makes it a lot easier
to work with, to sort of separate the concerns
of the dealing with the updating the DOM and dealing
with the actual logic and code.
So let's take a look at a few examples around that.
So I have some examples here.
So this is just a simple example of using a JavaScript object
and adding a few functions to it and then creating sort
of like a miniature application.
So it's very simple actually.
The only thing that it does is at first it prompts your name.
So I'll say Tim and then you can change your name to Bob.
And that's all this application does.
But what I'd like to point out is how it does it.
So I have this name generator object which has a start method
which asks the user for their name
by just calling this askForName
which down here it does the prompt
if name was not assigned then it asks for it again
by calling this askForName.
And then once it gets the name, it calls this update name.
So this then sets the user's name in the h1 tag.
And if the name is not set, it throws an error.
[ Inaudible Remark ]
Oh sure. So it sets the user's name in h1 tag
by calling setDisplayName which sets the HTML
in the JS name container and I'm prefixing all of my HTML
with JS selectors just because it's a good habit to get
into just to make it not so confusing
when you are using selectors like ID's or classes
for both style and for logic
in your JavaScript front end applications.
Because if you have different groups of people working
on the code base and you have a selector there
that the designer decides to change because it's--
doesn't look great, so they want to put in a new class and take
out yours and you're relying on it for JavaScript purposes,
then your code breaks.
It's good to prefix and sort
of like namespace almost the JavaScript-related classes
or attributes with a prefix of JS.
So this is pretty simple and you can see
in all these cases I'm calling return this at the end.
So this is a good habit to get into,
to give you it a valid return value.
In askForName I'm not because that makes sense
that you would get name back.
But what that allows you to do then
if you return this update name, it's returning the value
of setDisplayName which is returning the value of this.
And that allows you to sort of chain as you're used
to in jQuery by returning the value of this each time.
This refers to the current objects
so you could call this dot askForName dot setDisplayName
and it would keep the value of this and allow you
to have a nice chain there.
And then in-- so in this second example.
[ Pause ]
All right.
OK. So let's go ahead and open up the console
and go to my Sources tab.
We'll pop this out actually.
So in the Chrome developer tools that I mentioned,
there is this piece on the right and a--
you can see this stop sign although by default, it's black.
But when you mouse over it, it says "Don't pause on exceptions.
Click the pause on all exceptions."
And when you click it again, it turns blue.
And now anytime that there's an error thrown
in your JavaScript code, it'll stop at the point and allow you
to evaluate what's going on.
So-- And that's really a useful concept is about to point out.
And then if you click again, it turns purple
and this is normally what I keep it in.
It only breaks the code when there is an exception
that has not been caught.
So a lot of times in jQuery for instance, they do try catches
to test whether or not a browser has some sort of capability
and continue from there.
This is only when there's an error
that hasn't been caught in a try catch.
So let's try and submit a name that is blank.
So I can see that the code is now stopped
at the updateName method and I can mouse over names
and see it's empty to blank.
There it's equal to blank.
So if not name throw a new error and now I can step back
through the function column and say, "OK,
where did this come from," and see what the value of client is.
So it has askForName method,
setDisplayName start and updateName.
And this is just a really useful way you can see have all the
variables that are available in that scope as well
as the closure variables, so anything that's closed
over by this function.
And so I can see that-- what the value of client is
and what the value of this is.
So this 'cause we're in jQuery is equal
to the current DOM element.
But it's really useful for debugging code
to break on errors like this.
Another feature of the Chrome Inspector is
that at any point you can click on the different lines
in the row and it'll break at the places
where you have set breakpoints they're referred to as.
So if I click, the line turns blue.
So let me continue the execution here, OK, that broke.
And now let's set name to Alice and hit Submit.
So now I can see even before it got to the point
of updating everything, it's now stopped right here so I can see
that my this name is Alice and then I can continue--
let me reload the page.
All right, so now that it's starting at start again,
it has stopped at this line and I can see
that name is currently undefined.
askForName is which function it is, so that's also often useful
if you have functions that are coming from different files
or different places in the code, you can see where it is,
and then jump to that, it will highlight it.
So good to get in the habit of using debugging tools
that aren't just console dot log.
OK, so let's take a look at a second example
which makes more use of prototypes as I had alluded to.
So in this example,
we're creating a new function called CS
and this is capitalized so the convention standard
in JavaScript is if a function is supposed to be used
as a constructor, as opposed
to just a normal function, you capitalize it.
So I have capital CS and this takes a variable courseId
and courseTitle which I set to this courseId,
this courseTitle in the constructor.
And then I also set students and lectures as empty arrays.
So the reason that you--
OK, so the prototype properties were then defined
down here with-- so template is just a simple underscore
template, an underscore template being a way that you can--
similar to the templates that David had mentioned
on the server, you can just write a script tag
which is not a JavaScript script but a text HTML
and what I'm doing with jQuery is--
it doesn't keep these open, yeah, there we go.
With jQuery, it's getting the HTML value of that template
and then running it through the underscore utility libraries
template engine.
So the documentation for that is down here
under the utility template
but basically you can read a little bit more about it.
But it evaluates this string and turns it into a function
which we can then pass data into and it call dynamically.
The next two methods I have are addStudent and addLecture.
These just add them to the internal arrays that I've set
in the constructor and then the render method.
So, let's create the new instance of CS called 164
which has this course number 164 and title.
And then CS50 which has CS50 and intro to CS1
and then add a few lectures students
and then call CS50 render.
And if I run code, so I'm doing that with Eval.
You never really want to use the Eval, but I'm just sort
of taking all the JavaScript that's in here
and executing it on the fly.
It renders into this template these new instances
of the CS class which have the properties, so we've gone
through and done addLecture and addStudent to each.
And as I mentioned because I'm returning this,
I can actually chain these addLecture and addStudent calls
and it'll work just as well.
The other feature in JavaScript that is even more useful
on the server side where you really at any given time
if your application gets bigger don't know where you are
and it's harder to set these individual breakpoints
that I mentioned in the Chrome Inspector is
to use the debugger keyword.
So it's just D-E-B-U-G-G-E-R.
And when you put a debugger keyword in your code
and you have the-- there we go, two Gs.
When you put the debugger keyword in your code
and you're running a debugger
such as the Chrome Inspector here
or the server side Chrome Inspector, it tells JavaScript
to stop execution on that line of code and then it allows you
to step through the rest of the execution of codes.
So if I click run code here, it's now stopping
at this debugger line and I can see OK, here's the value of CS50
and it's a got course title, course ID,
it's got no lectures, no students.
And then I can step through the whole addLecture,
I can see it's pushing on to these lectures,
mouse over that, "Hello World".
I can actually in the console do this so this is set
to the current object that you're in.
This lecture is "Hello World".
And keep stepping through as much as I want.
If I don't want to step
into a function call 'cause I know what that's going
to do going into addLecture, there's this button right here
which says "Step over the next function call," and so I can go
to the point were I'm maybe wondering about something.
Like for instance 164 render.
So at this point, it's going to be rendered.
I can see this template is the compiled template.
I can see at this point I should have two students
and two lectures.
And then there's the prototype chain that I was referring to.
So the default one that comes along with just an object
in JavaScript in general,
it comes with two string value of constructor.
And then the ones that I've added on myself
with the addLecture, addStudent and then the properties
that are unique to this instance of the class
as it was invoked with the new keyword.
So let's do just one more example on this
and then we'll step to some more interesting things
on the server side.
So let's go ahead and open this last example which is--
let's see, where is the code?
I don't know where this went.
OK, well, we might just skip over this code then actually--
oh hold on, I think I missed the style sheet for the code.
OK, so let's make this a little bigger.
In this example, I'm showing a little more on the setting
up the prototype chain,
so setting up inheritance with the JavaScript.
So in this case, we have a catalog which is going
to presumably maintain multiple courses.
And so a catalog has an addCourse methods.
So it checks whether the course that's passed in is an instance
of course as invoked with the new keyword.
So if you try and send
in something different, it will yell at you.
The render method which will render each of the courses
by compiling its template below.
And we have the course which access
in this case the base class for individual department courses.
And instead of setting each
of the course dot prototype dot method
or property using the extend helper in the underscore library
to sort of call extend this prototype with all
of these properties, which is useful, a little easier to read.
And then down here doing what's known as setting
up the prototype chain.
So this is actually a little tricky to people at first
and even still having done this for awhile, it's sort of hard
to wrap your head around.
But don't let that scare you.
So I'm setting up a new--
an entirely new class object here, CS.
And in the constructor,
I'm saying course apply this arguments.
So arguments is a special value I guess you could call it
in JavaScript, the keyword which has all
of the everything that's passed along is arguments
that function are available with the arguments call,
with the arguments keyword.
So as I'm calling with course dot apply,
this is the current context with which CS is being called.
So when I invoke it with new it's a-- it's a value of CS.
And I'm saying call this course method up here.
Oh sorry-- call this course method right here
but set the value of this to be whatever the value
of this is right here.
So the apply keyword allows you to sort of change the state
of this which is how jQuery is allowed to sort of switch
out this on you as you're going through
and make a DOM elements instead of the jQuery object.
So now I'm going to set a temporary function
which will grab the prototype of the course.
And sort of set it to its prototype
and then set the prototype on the CS function object
to a new instance of that.
So basically I'm saying instead--
if I down here did CS dot prototype equals new course.
Then it would be calling everything
in this constructor function,
which I wouldn't necessarily wanted to.
So all I'm doing is sort of creating almost
like a surrogate function which will have the courses prototype
on it and sort of mimic the prototype--
the course but without doing everything in the constructor
and set that to the prototype.
And then I'm just adding so the department
in this case is Computer Science for the CS object.
And then I have a sort of a bridge version of doing that.
It doesn't work in IE9.
So that's why I wanted to show sort of how--
what this is doing under the hood.
But you can set it up in the same way
where Econ equals function course apply these arguments
and then say Econ dot prototype equals object dot CreateCourse
dot prototype.
So it's creates a new object which is just the prototype
for the course and then set the department there.
So now let's just go set a debugger here and click on run.
There we go.
So CS164 we can see the prototype chain we've got the
properties which were set in the constructor.
So values of these that were set and then on the prototype chain
for the CS object it had department Computer Science set.
And then on the underlying prototype chain,
we then have all the methods and properties
that are unique to the course object.
And then we have the base objects.
So that sort of a quick example of the prototype chain.
And as you can see here, there are two values per department.
So there is department of computer science
and then department not listed which I said
as the default value here.
So the prototype chain is actually just a singly
link list.
And as it tries to find a property,
it'll start at the top level value.
So what's the defined in the constructor function
and then sort of go down the prototype chain from there.
So because it found, so--
if right here, I say CS50 dot Department,
it'll say Computer Science.
But if I say var--
[ Pause ]
But if I say humanities equals new course
and then I say humanities dot department,
I'll see department not listed because it went to first the--
I can look at the prototype chain here actually.
So it went first to the course object and saw there's nothing
on the prototype chain at this level for the department
or for the department values so then it jumps to the next level,
the course and looks forward there and finds it.
So it just sort of like goes down from the top down
and that's sort of something that's unique
about JavaScript is that you can change any
of these values at any given time.
So in the constructor or in an individual method on the object
if I want to set this department to something new,
or if I even want to set any of these functions
that are already exist
to something new, I'm free to do that.
So right now I have CS50 dot addLecture, looks like that.
And if I want to set it to CS50 addLecture just equals
to blank function.
Then now I can see it's just completely changed
which you're not able to do another languages
where you have a stricter class based inheritance
and everything is sort of set up.
JavaScript is very, very flexible with regards to that.
OK, let's jump back in the slides.
So if for instance you would always like a function
to have a particular this value set for it.
You can call function dot bind
and set what the value of this should be.
You can think of it as--
"I'm trying to think of a good real world example but",
if you want to protect your code
against somebody potentially calling it with a value
that wouldn't be this.
Like for example AJAX callback like excess or error.
Those are typically not called
with a good semantic value of this.
And you're like, "OK, I always want this to be the value
of the course object that I'm working with.
Or the view which I'm working with in my code
that represents this DOM node, you can set--
you can bind context to this and then when it's called later
by jQuery and it doesn't have a good value of this it'll stick
to what you bounded it with.
Then there's function call were you can specify the context
and specify any variable number of arguments.
And then there's function apply which you can pass
in the context and then either an array
or the arguments objects that I mentioned as you see there.
And the arguments in any function that you call,
you can just type in the word "arguments"
and it'll have all the arguments.
It has a "length" property
which is how may arguments were actually passed to that methods
since in JavaScript you can sort of call
with variable numbers of arguments.
It's useful for saying if this had one argument,
then follow this code path.
If it had two, you might want to follow another way.
It allows you to have really dynamic APIs for your methods.
You can think of that with jQuery
like when you have dollar dot on or bind.
And it sort of does different things
as to whether you put one argument or two or three
or start it with a function.
It is using the arguments property
and the arguments length in a lot of cases
to have this magic functionality happen.
The things you can't do with arguments is use it just
by default as an array.
So you can say arguments three and set it to something
as you could using the array assignment.
You can use the-- a lot of the underscore methods
for either collections or for working with arrays,
you can pass in arguments and it'll realize
that it's an arguments object and sort
of take care of that for you.
But if you want to use the arguments that are passed
through a function as an array,
you can use underscore dot two array.
One of the number of utility functions
that are build in to underscore.