Object-oriented Programming in JavaScript: Made Super Simple | Mosh

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] so what is object-oriented programming object-oriented programming is a programming paradigm or a style of programming that is centered around objects rather than functions it's nothing new it's been around since the 70s but unlike tools and frameworks that come and go object-oriented programming is still very relevant today that's because it's not a programming language or a tool it's a style of programming or a programming paradigm there are several programming languages out there that support object-oriented programming such as c-sharp Java Ruby Python JavaScript and more now JavaScript is a little bit controversial but I'll get to that later it may interest you to know that many of the popular frameworks out there that you might be using are actually designed with object-oriented programming concepts in mind angular is an example of these frameworks so object-oriented programming is a very popular style of programming and it comes up in many technical interviews so if you really want to be a serious developer you need to understand object-oriented programming as a technical interviewer myself if I see a candidate with object-oriented programming under resume that candidate stands out to me and that's where this crash course comes in in this course you're going to learn and understand object-oriented principles and how to implement them in JavaScript my name is Mohamad ani and i'm going to be your instructor in this course if you enjoyed this video please like and share it with others and be sure to subscribe to my channel for new videos every week you can also follow me on twitter as Masch a Madani so now let's get started a popular interview question concerns the four core concepts in object-oriented programming this concepts are encapsulation abstraction inheritance and polymorphism let's look at each of these concepts before object-oriented programming we had procedure of programming that divided a program into a set of functions so we have data stored in a bunch of variables and functions that operate on the data this style of programming is very simple and straightforward often it's what you learn as part of your first programming subject at a university but as your programs grow it will end up with a bunch of functions that are all over the place you might find yourself copying and pasting lines of code over and over you make a change to one function and then several other functions break that's what we call spaghetti code there is so much interdependence e between all these functions it becomes problematic object-oriented programming came to solve this problem in object-oriented programming we combine a group of related variables and functions into a unit we call that unit an object we refer to these variables as properties and the functions as methods here's an example think of a car a car is an object with properties such as make model and color and methods like start stop and move now you might say what marche we don't have cars in our programs give me a real programming example ok think of the local storage object in your browser's every browser has a local storage object that allows you to store data locally this local storage object has a property like length which returns the number of objects in the storage and metals like set item and remove item so in object-oriented programming we group related variables and functions that operate on them into objects and this is what we call encapsulation let me show you an example of this in action so here we have three variables base salary over time and rate below these we have a function to calculate the wage for an employee we refer to this kind of implementation as procedural so we have variables on one side and functions on the other side they're hard decoupled now let's take a look at the object-oriented way to solve this problem we can have an employee object with three properties a salary over time and rate and a method called get wage now why is this better well first of all look at the get wage function this function has no parameters in contrast in a procedural example our get wage function has three parameters the reason in this implementation we don't have any parameters is because all these parameters are actually modeled as properties of this object all these properties and get wage function they are highly related so they are part of one unit so one of the symptoms of procedure code is functions with so many parameters when you write code in an object-oriented way your functions end up having fewer and fewer parameters as Uncle Bob says the best functions are those with no parameters if fewer the number of parameters the easier it is to use and maintain that function so that's encapsulation now let's look at abstraction think of a DVD player as an object this DVD player has a complex logic board on the inside and a few buttons on the outside that you interact with you simply press the play button and you don't care what happens on the inside all that complexity is hidden from you this is abstraction in practice we can use the same technique in our objects so we can hide some of the properties and methods from the outside and this gives us a couple of benefits first is that we'll make the interface of those objects simpler using an understanding an object with a few properties and methods is easier than an object with several properties and methods the second benefit is that it helps us reduce the impact of change let's imagine that tomorrow we change these inner or private methods none of these changes will leak to the outside because we don't have any code that touches these methods outside of their content object we may delete a method or change its parameters but none of these changes will impact the rest of the applications code so with abstraction we reduce the impact of change now the third core concept in object-oriented programming inheritance inheritance is a mechanism that allows you to eliminate redundant code here is an example think of HTML elements like text boxes drop-down lists checkboxes and so on all these elements have a few things in common it should have properties like hidden and inner HTML and matters like click and focus instead of redefining all these properties and methods for every type of HTML element we can define them once in a generic object call it HTML element and have other objects inherit these properties and methods so inheritance helps us eliminate redundant code and finally polymorphism poly means many morph means form so polymorphism means many forms in object-oriented programming polymorphism is a technique that allows you to get rid of long ethanol's or switch and case statements so back to our HTML elements example all these objects should have the ability to be rendered on a page but the way each element is rendered is different from the others if we want to render multiple HTML elements in a procedural way our code would probably look like this but with object orientation we can implement a render method in each of these objects and the render method will behave differently depending on the type of the object viewer referencing so we can get rid of this nasty switch and case and use one line of code like this you will see that later in the course so here are the benefits of object oriented programming using encapsulation we group related variables and functions together and this way we can reduce complexity now we can reuse these objects in different parts of a program or in different programs with abstraction we hide the details and the complex and show only the essentials this technique reduces complexity and also isolates the impact of changes in the code with inheritance we can eliminate redundant code and with polymorphism we can refactor ugly switch case statements to go through this course all you need is a code editor and a simple web server the editor that I'm gonna use here is Visual Studio code or vs code that you can download from code that Visual Studio calm but feel free to use any editors now with vs code we have this extensions panel here search for live server this is a very simple and lightweight server that we're going to use to serve our application so install is and then here in the files panel let's add a new file index dot HTML now to generate some basic HTML template we can simply type an exclamation mark and press tab so a very basic HTML template now let's add a script element so script with source set to index J s we're gonna write all our JavaScript code inside of this file so let's add a new file and save it as index that J s and finally to make sure that we have setup everything properly let's do a console that log of hello world now when you install live server you should get this menu here in the status bar if you don't see that you probably have to restart vs code and if you still don't see it simply right-click on index.html and select open with live server so this will fire up Chrome pointing to this address now let's open up Chrome developer tools here in the console tab we've got hello world so before going any further I want to emphasize that this course is not for beginners is for intermediate level developers so you should have at least three months of experience programming in JavaScript you should know the basics you should know how to use Chrome developer tools I'm not gonna cover these in this course our focus is purely on object oriented programming with JavaScript javascript is all amount objects so in order to learn object-oriented programming first you need to have a good understanding of objects so in this section I'm gonna cover some fundamental concepts around objects such as creating objects factories and constructors primitives and reference types on how they behave differently working with the properties of an object such as adding removing properties as well as enumerating them you're also gonna learn how to define private properties as well as getters and setters if you know all these topics well feel free to skip this section and move to the next section where I talk about prototypes otherwise continue watching so now let's get started let's start this section by creating an object so I'm gonna use the let keyword in es6 which is the replacement for var so in es5 and before we had var for declaring variables but for has a number of issues when it comes to scoping that's beyond the scope of this course I just want to let you know that as a best practice stop using var use either let or Const with cons you're basically defining a constant so you won't be able to reassign it if you want to reassign a variable use let now in this demo I'm gonna use Const to define a constant so let's call this circle and set it to an object here I'm using object literal syntax so these curly braces we refer to them as object literal syntax an object in JavaScript is essentially a collection of key value pairs so inside these curly braces I'm gonna add a few key value pairs let's add radius and set it to 1 let's add another key like location now this time the value can be an object so again I'm using object literal syntax in this object we can have a couple key value pairs like x and y now let's add another key value pair so the keys draw the value is a function that is for drawing the circle so for now let's just do a simple console.log now I want to define a few terms here this circle object has three members radius location and draw if a member is a function we refer to that as a method so here we say draw is a method these other members are what we call properties now in some JavaScript tutorials that refer to all these members as properties whether there are functions or not but technically in object-oriented programming properties and methods are fundamentally different because a property is used to hold values a function or a method is used to define some logic so now that we have this circle object we can access its members using the dot notation so circle dot look here are the members we can call the draw method now note here on the right side I've got Chrome open this is Chrome developer tools as soon as I save my changes here you will see that Chrome is gonna refresh because here with live server we have hot reloading so save and here's the result so as soon as we change our code the new code is loaded inside Chrome so object literal is a simple way to define an object but we can also define objects using factories and constructors and that's the topic for the next lecture all right now let's imagine we want to create another circle with the current implementation we have to duplicate all this code like this now this can be a problem if we have one or more methods in our object in this case we have this draw method here and as you can see we have duplicated that in two different places so if there is a bug in this method we have to come back and fix it in multiple places now this is a very simple object imagine if the circle object had ten methods so object literal syntax is not a good way to create an object and duplicate it if this object has at least one method if an object has one or more methods we say that object has behavior like a person that can do different things so it has behavior now let's imagine here we didn't have this draw method duplicating this object wouldn't be a big deal so basically we would end up with two objects and then here we could use different values so creating objects with the object literal syntax is an issue only if that object has behavior so what's the solution the solution is to use a factory or a constructor function so let me show you how that works I'm going to delete this second circle and define a function called create circle now I'm gonna move all this code inside this new function like this now we don't need to declare a constant we can simply return this object now this circle requires a radius so instead of hard-coding one here I'm gonna add a parameter here radius and then set that here now in es6 we have this new feature so if the key and the value are the same we can remove the noise in the code by removing the value so we can only add radius now to simplify the code so you can focus on what I'm gonna teach you I'm gonna drop this location property we don't really need it instead I'm gonna add our draw method so key value and let's do a simple console nut lock draw okay so this is what we call a factory function now we can simply call this function to create a new circle so constant circle we call create circle and pass one as the radius now there is another way to create an object using a constructor function so let's delete circle draw and define a constructor function I want you to see them side by side so once again we define a function but the naming convention we use for a constructor function is different the first letter should be uppercase so we call it circle with an uppercase C the developers with background in languages like C sharp and Java this kind of looks like a class however as you can see we're defining a function in JavaScript we don't have the concept of classes so our circle function is gonna take a radius parameter but in the body instead of returning an object we're gonna use that this keyword to set the properties of this object what is this this is basically a reference to the object that is executing this piece of code you're gonna see that in a second so imagine we have a new empty object in memory now we're gonna use this to reference that object and then use dot notation to set various properties on that object so we can set the radius property to this radius argument similarly we can define another property draw but this is more accurately a method so we set it to a function and here we do a console dot log of draw okay now we can create a new circle like this we use the new operator to call the circle function and pass one as the argument let me use the new operator a few things happen under the hood this new operator will create an empty object so like this an empty object then it will set this to point to that object because by default this points to the global object if you're running this code inside of a browser the global object is the window object if you're running it inside a node environment the global object is global let me show you so I'm gonna do a console that log of this let's see what happens so save the changes now look this is this circle object here and here we have two members draw and radius this is because we use the new operator here if I remove that let's see what happens so save the changes now this reference is the window object so this is the global object in a browser we don't want to use this we don't want to mess up with this we don't want to define global variables because they're bad practice because they're available everywhere in our application so it is possible that one function or another will modify the value of these variables accidentally and create bug in our application so when we use the new operator to call a function three things happen first this new operator will create an empty object then it will set this to point to that object and finally it will return that object from this function so note that here we don't have an explicit return statement we are not returning this this will happen automatically when we use the new operator so let me delete this also we don't need console that log here so basically we have two ways to create an object we can use a factory function or a constructor there is nothing special about this they're both regular functions in JavaScript if we return an object in this function we refer to that function as a factory function in contrast if we use that this keyword along with the new operator we refer to that function as a constructor function now you might ask what is the difference between these two patterns for creating an object which approach should you well it really depends who you ask developers coming from languages like C sharp and Java preferred the constructor function syntax because this looks like creating an instance of a class but once again in JavaScript we don't really have classes other developers don't like this approach they prefer to use Factory functions and one of their arguments is what if a developer forgets to use the new operator here then we're defining these property methods on the global object which is in this case the window object but this discussion this argument is really outdated with the modern JavaScript and the tools that are available to us we get an error if we forget to use the new operator here so my suggestion to you is not to get hung up and this religious arguments about factories versus constructors as a developer you should be familiar with both these patterns because as you work on different projects and different teams you will see both of these patterns for creating an object so you should understand how they work choose the pattern that you prefer every object in JavaScript has a property called constructor and that references the function that was used to construct or create that object so here we have two objects circle and another let's look at the constructor property so here on the console another dot constructor so as you see this returns our circle function that we use to create this object now let's look at circle dot constructor what is this well you can tell that this is a function because here we have this blue F and as you can see the first letter of this function is uppercase so this is a built-in constructor function in JavaScript when we create an object using the object literal syntax internally the JavaScript engine uses this constructor function let me show you so I'm gonna temporarily delete all this code let's define an object like this let me use this syntax object literal JavaScript engine will translate that to something like this let x equals new object okay so this circle object we created and returned it from our factory function and because we use the object literal syntax internally it was created using this object constructor function in JavaScript we have a few other built-in constructors for example we have string for creating strings but queen' often we use string literals so single code or double quote or backtick using these literals is cleaner and simpler than using the constructor you also have boolean but again we don't use this we either use true or false so we refer to these as boolean literals we also have number but instead we use number literals like 1 2 3 whatever so this is what I want you to take away every object has a constructor property and that references the function that was used to create an object one of the confusing concepts in JavaScript is that here functions are objects so this circle function we have here is actually an object don't believe me let me show you so circle dot look these are all the members of this circle function or circle object so the purple icons are methods like call bind and apply and the blue icons are properties so let's take a look at a few of these members in the console here in the console circle dot name that returns the name of this function circle the length returns the number of arguments now earlier in the last lecture I told you that every object in JavaScript has a constructor property and that references the function that was used to create an object but here's the interesting part who do you think created this object let's have a look so circle dot constructor so here we have another built-in constructor called function and let me declare a function using this syntax internally JavaScript engine will use this function constructor to create this object let me show you so I'm gonna define a constant called circle one two separate from our circle set it to new function now here our function requires one parameter radius so we add that here as a string now as the second argument I'm gonna pass the code inside of this function so to break it up into multiple lines I'm gonna use the backtick character and then simply copy all this code and put it here so when we declare a function internally it's represented like this now we can call this circle one just like calling our circle function so we can create a circle object by newing up circle one and pass one as the radius save the changes now in the console let's log circle look it's a real circle object with these two members now let's take a look at a couple of methods that are available in our functions so I'm gonna delete all this code circle dot here we have this call method and with this we can call a function look at the arguments the first argument is this argument here we need to pass an empty object and this will reference this object that we pass here okay after that we add our arguments explicitly so here we have one argument we pass one if you had multiple arguments we would pass them explicitly like this okay so this expression is exactly like expression on line 11 when we use the new operator this new operator will internally create an empty object and pass them as the first argument to the call method and this object will determine the context for this so this will reference this object earlier I told you that if you don't use the new operator this by default will point to the global object which is window so if I want to rewrite this expression in this way instead of passing an empty object I would pass window of course we don't want to do this I'm just explaining to you what happens under the hood so let's revert this back so the argument here specifies the target of this okay now we have another method called apply it's exactly like the call method with this we can call a function but instead of passing all the arguments explicitly we pass them in an array so this is useful if you already have an array somewhere else in your application and you want to pass an array as the second argument to the apply method so this is the takeaway in JavaScript functions or objects hi guys Marsh here thank you for watching my youtube tutorial I just wanted to quickly let you know that this video you've been watching is actually the first hour of one of my courses called object oriented programming in JavaScript so when you get to the end of this tutorial if you feel like you want to learn more click on the link in the video description and enroll in the course and if not that's perfectly fine continue watching as the next section is coming up in JavaScript we have two categories of types on one side we have value types also called primitives and the other side we have reference types so in the value types category we have number string boolean symbol which is new in es6 we're going to look at that later in the course as well as undefined and know these are the primitive or value types on the other side we have objects functions and arrays so in the last lecture you learned that functions are also objects the same is true about a race so in a nutshell in JavaScript we have primitives and objects now in this lecture I'm gonna show you how primitives and objects behave differently because this is absolutely important for you to understand before we move on to the next section where I talk about prototypes so on this empty canvas I'm gonna define two primitives x and y I'm gonna set Y to X so here Y is 10 now I'm gonna change the value of x to 20 what I want you to note here is that X and y are two independent variables so I save the changes go back in the console let's log X X is 20 and Y is 10 they are independent so when we work with primitives this value is value that we have here is stored inside of this variable when we copy that variable that value that is stored in the variable is copied into this new variable so they are completely independent of each now let's see what happens if we use a reference type or an object here so I'm gonna change this to an object that has a property called value and then instead of setting X to 20 I'm gonna set X code value to 20 so save the changes back in the console let's log X so you can see by the properties 20 now let's log Y we can see the value property of Y is also 20 so this is the takeaway when we use an object the object is not stored in this variable that object is stored somewhere else in the memory and the address of that memory location is stored inside that variable so then when we copy X into y it's the address or the reference that is copied in other words both x and y are pointing to the same object in memory and when we modify that object using either X or Y the changes are immediately visible to the other variable so here's the conclusion primitives are copied by value reference types or objects are copied by the reference let's take a look at another example so I'm gonna define a function called increase that takes a number and here we simply increase this number by 1 let's declare a number variable and set it to 10 and then call increase and pass this number now if I log this number on the console what do you think we're going to see let's have a look so save the changes we see 10 but dinner we increase the number well when we call increase and pass this number variable its value is copied into this parameter that is local in this function so this number variable here is completely independent of this other number variable here in this function we increment number by 1 so it will be 11 but after this function this number is going to go out of the scope so when we log this number on the console we're essentially dealing with this first number so I told you that primitives are copied by their value so here we're dealing with two independent copies that's why we see ten on the console now let's change this to a reference type or an object so I'm gonna change ten to an object that has a value property okay let's rename this variable to object and similarly I'm going to rename this parameter in this function to object and then increment object dot value now when we log this on the console what do you think we're gonna see we're gonna see eleven see we got this object with value 11 the reason for this is because when we call increase and pass this object this object is passed by its reference so this local parameter that we have here will point to the same object as we defined here so in this case we are not dealing with two independent copies we have two variables that are pointing to the same object so any changes we make to this object will be visible to the other variable so remember this in JavaScript we have value types also called primitives as well as reference types which are objects our primitives are number string boolean symbol undefined and no primitives or value types are copied by their value reference types or objects are copied by the reference all right so here we have our circle constructor function and using that we create a circular object now these objects in JavaScript are dynamic that means after you create them you can add extra properties in them or delete some properties you might be wondering why this is useful in the real world imagine you're working with a user object the client that can be a web or a mobile application is going to send a user object to the server on the server we get this user object and then we add additional stuff to it for example we can add a token property that we generate on the fly on the server so we can always add something extra to an existing object because we don't have classes we don't need to define these properties ahead of time we can add them whenever we need them and this makes JavaScript extremely powerful and easy to work with in languages like C sharp or Java every time we want to implement scenarios like this we have to go back and change our classes so here let me add a new property to our circle object we can set the location here like this save the changes now here on the console let's log circle all right you can see here we have two properties location and radius we also have another notation for accessing properties that is bracket notation so another way to rewrite this code is like this we use brackets and use a string to reference a property so location it's exactly the same as we can see the dot notation is simpler and less verbose than bracket notation but this notation is also useful in certain scenarios for example when you want to dynamically access a property name for example let's imagine we have this constant called property name set to location you have that somewhere in our application now we want to access the location property of a circle if you're dealing with this dynamically at a time of writing the code we don't know what is the name of that property that is calculated at runtime so we can type something like this circle that location but what we can do is use the bracket notation so we use circle brackets property name another use case for using the bracket notation is when you are using the property names that are not valid identifiers for example let's imagine the name of this property is Center - location we can access this property like this circle that Center - location that doesn't work so if you have special characters or a space that's when you use the bracket notation okay now we can also delete a property from an existing object a real word use case for this is when you get a user object from a database and you want to return it to the client but maybe that user object has certain properties you don't want to send to the client you don't want to send the password you don't want to send the credit card info in that case you will dynamically delete one or more properties from an object so we use the delete operator and then reference the property name so circle dot location again here we can use the dot notation or brackets of course here we need a string sometimes you need to iterate over or enumerate the properties in an object we can do that using the for in loop so for let key in circle so in every iteration key will hold the value of one key in this object let's log that on the console okay so look we have radius and draw so it's returning both properties and methods now if you want to get the value of these properties you can use the bracket notation so here and console the log I'm gonna log circle of key you learn in the last lecture lab we can use the bracket notation to access a member okay so say now you can see radius is 10 and draw as a function what if we want to get only the properties and not the methods well we can use the type of operator to check the type of this value so if typeof circle of key it's not equal to function then we will display it on the console save the changes now we get only the radius there is another approach to get all the keys and an object so it's object that we have has a method called keys we can pass our circle object here and this will return all the keys in the circle as an array so let's store them here and lock them on the console so here we have an array with two members radius and draw with this approach we cannot separate properties from methods now finally sometimes you want to know if an object has a given property for that we use the in operator so if here we add the name of the proper as a string if radius is in circle we do a console that log of circle has a radius okay save the changes and here's our message so remember to enumerate all the members and an object you can use a four in loop to get all the keys and an object use object that keys and to check for the existence of a property or a method in an object use the in operator all right now let's introduce some complexity in this example so I'm going to define another property called default location set it to an object like this also let's define another method compute optimum location we set this to a function and here we're going to do some magic it doesn't really matter what matters is that we're going to call this method inside of the draw method so we call this dot compute optimum location now there is a problem with this implementation let me show you so here when we create the circle object circle dot these are the members of our circle object not all these members should be accessible to me as the consumer or the client of this object for example what would happen if I set default location to false it's gonna completely mess up with this object or as another example maybe this compute method should only be called inside of the draw method so if I accidentally call it here circle the compute optimum location maybe this will put this object in a bad state and then if I call circle but draw we're gonna get a weird error at runtime so in object-oriented programming we have this core concept called abstraction abstraction means we should hide the details and complexity and show or expose only the essentials in this particular example we should hide this property default location as well as this method these are implementation details these are part of the complexity of this object we want to hide these from the consumers of this object instead we want to expose only the essentials that is the radius and the draw method let me give you a metaphor think of a DVD player a DVD player has a complex logic board on the inside but only a few buttons on the outside that you interact with so what we have on the inside is the implementation detail and what we have on the outside is the public interface of it we player we want our objects to look like this DVD player we want to hide all the details all the unnecessary complexity on the inside and expose only a few members or a few buttons on the outside a lot of developers who have not been able to apply object-oriented programming effectively have failed to comply with this principle everything in their objects is public and accessible from the outside and this will bring a number of issues one issue is that every time you change the implementation of that object you have to go and modify many different places in your code for example let's imagine now this compute method requires an argument let's add a factor argument here with the current implementation because we can access this from the outside everywhere we have used this method you have to come back and pass an argument so one simple change in the implementation of an object results in a number of changes in your source code in contrast imagine if this method was not accessible from the outside then we wouldn't have to modify this line it would only modify line 12 where we have called this function right so remember the abstraction principle of object-oriented programming hide the details and expose only the essentials in the next lecture I'm going to show you how to implement this in JavaScript so how do we implement abstraction here you want to hide certain members from the outside so earlier you learned that this references that new circle object now what happens if I declare a local variable in this function let's say color we set that to red is this going to be part of that object of course not because we have not set that as a property on that object we didn't set this that color to color okay so this is only a local variable inside of this function when we get out of this function this variable goes out of scope and dies now with this technique we can easily hide certain members from the outside so default location is implementation detail we don't want this to be accessible from the outside instead of setting it as a property on our new object we define it as a local variable here okay now we don't need this color anymore by the same token we can convert this method to a private method so let compute be a function now here in the draw method recalling compute optimum location this function will no longer be a method on this new object so we can access it using this you have to access it directly here this will work because in JavaScript we have this concept of closure if you don't know closure let me simplify it for you so here we have one function and another function inside of that function in this function we can declare certain variables like X and Y and these are local variables that are only available in this function their scope is limited to this function so when we finish executing this function x and y will go out of scope in contrast to scope we have closure a closure determines what variables will be accessible to an inner function so this function will be able to access all the local variables defined here as well as the variables defined in its parent function so here we declare it two variables compute optimum location which is a function as well as default location these are the variables that are defined in this parent function they are within the scope of this function but within the closure of this inner function now don't confuse closure with a scope because the scope is temporary and it dies so every time we call the draw method these variables will be recreated and reinitialized and then after this function they will die so scope is temporary but closure stays there so when we call the draw function after we finished executing this function these variables will continue to stay in memory they will preserve their state because they are part of the closure of this draw function okay so back here so in this method if you want to access those private members you simply use them here you can also use default location default location but if you want to access members of this new circle object you need to use this so this dot radius as an example okay now with this simple change we basically replace this with let let's see what happens if I access the members of the circular object we only see draw and radius so the public interface of this object is simpler is easier to work with and this will also prevent issues later down the road so in the last lecture we converted these two members to private members now more accurately these are not private members of the circle object because technically they are not inside of a circle object there are local variables that we have defined inside of this circle function but from an object-oriented point of view we can refer to them as private members of the circle object now I want to simplify the code here so we can focus on a small issue I'm gonna delete this compute function right so we have this private property default location we cannot access this from the outside but what if we want to display that default location somewhere in our application so we don't wanna modify it we just want to be able to read it so one solution is to define a method here this dot get default location we set it to a function and in this function we simply return default location once again we're dealing with an inner function here the closure of this function includes all the variables defined here as well as all the variables defined and its parent functions so here we have access to default location and with this we can call circle dot get default location however I don't like this syntax I don't like the fact that we're calling this as a method it would be nicer if we could access this property like this default location but we shouldn't be able to set this from the outside we can only read it so let me show you how to define a property like that so this object that you have seen so far has a method called define property we have another method called defined properties if you want to define multiple properties in one go now the first argument of this method is the object that we want to add a new pretty - now the object is the one that is referenced by this the new circle object right so we pass that here the second argument is the name of our property we want to call that default location and the third argument is an object in this object we add a key value pair the key is get this is a special keyword for JavaScript and the value is a function so when we access circle dot default location this function will be called okay now here we can simply return default location again this variable is part of the closure of this inner function so here we can access it right now in vs code you don't see that in intellisense so we don't have default location as a property however if we save the changes oops I made a mistake here actually I should have used define property so save the changes all right so now look at the circle object circle so here's our new property default location you can see dot dot dot in front of it because this is a computed property when we click this that get function will be executed and here's the result our default location okay also you can see that function is stored here as a getter so a getter is a function that is used to read a property so this property we have here default location we refer to this as a read-only property now if you want to set the value of this property from the outside we define a setter so in this object we add another key value pair the key is set which is a special keyword and the value is a function now this function takes an argument called value we can set this default location that is value but what is interesting is that because we are using a function in this function we can perform some validation for this value before setting the default location for example we can write a simple logic like this if value that X is falsey or value that Y is false e we can throw a new error again error as a built-in constructor that we use to create error objects we pass a string invalid location so this is the benefit of a setter now we can come here and set circle duck default location let's see what happens if we set this to 1 save the changes and here's our error invalid location so to recap use object at define property to define getters and/or sellers here is a great exercise for you I want you to use what you have learned in this section and design a stopwatch object like this so let me show you how this behaves I'm going to define a constant called SW and set it to a new stop watch so that's our stopwatch object now this object has a few members duration which is a property as well as three methods reset start and stop and the other members you see here they are inherited from the base object okay now initially duration is zero we can start the stopwatch now at this time if we call start again it's gonna scream at us stopwatch has already started so we cannot call start twice now we can call stop and again we cannot call stop twice in a row it's gonna complain because stopwatch is not started now we can access the duration property so stopwatch oops sorry so stopwatch dot duration so this stopwatch counted 19 seconds from the moment I called the start method until I called the stop method now we can repeat so if we call start again now it continues counting and then we call stop and then let's look at the duration again now it's a total of 20 seconds we can also call reset and this takes the stopwatch to its initial State so we can call start and then stop and then look at the duration only 2 seconds ok so this is how this stopwatch works now I want you to go ahead and spend about 30 minutes on this exercise use what you have learned and do your best to implement an object that behaves like this in the next lecture I'm going to show you my solution alright here's my implementation of the stopwatch object now don't worry if your implementation is different from mine chances are it's gonna be different because there is no one solution to a given problem as long as your stopwatch behaves like what I showed you in the last lecture and it has a clean implementation your solution is perfectly fine so here we have a function called stopwatch this is a constructor function I have defined a few private variables here start time and time running to see if the stopwatch is running or not and duration which you have initially set to zero you can see we have three methods here start stop and reset and I've also defined a read-only property called duration look here we have a getter which simply returns this duration which is a local variable in this function okay now let's take a look at the implementation of each of these methods so start first we have a validation check if the stopwatch is running we simply throw a new error with this message stopwatch has already started otherwise we set running to true and set start time to the current day time very simple implementation the stop method is very similar so first we have a validation check if it's not running obviously we cannot stop it that's why we throw a new error otherwise we set running to false next we set n time to the current date time and then we calculate the second between the end time and start time so we call n time that get time and subtract it from start time get time this expression returns the milliseconds between these two date objects so we divided by a thousand to get the seconds and then add that to the duration variable which we defined earlier and finally let's take a look at the reset method here we simply set these variables to their initial value so we set start time and end time to null running to false and to zero so once again if your implementation is different don't worry there is no one best solution to a given problem if I come back and solve this problem in a month from now chances are my implementation is gonna be different from what you see right now well hello it's me mash again I wanted to say thank you very much for watching this tutorial to the end I hope you learned a lot please share and like this video to support me if you want to learn more about object-oriented programming as I told you before I have a course called object-oriented programming in JavaScript this video you have been watching is the first hour of that course if you want to learn more click on the link in the video description and enroll in the course if not that's perfectly fine make sure to subscribe to my channel because I upload new videos every week thank you and have a great day
Info
Channel: Programming with Mosh
Views: 1,074,922
Rating: 4.9391031 out of 5
Keywords: oop, object-oriented, object-oriented programming, object oriented programming, javascript, node, angular, react, vue, object, prototypes, prototypical inheritance, this, inheritance, polymorphism, programming with mosh, code with mosh
Id: PFmuCDHHpwk
Channel Id: undefined
Length: 62min 49sec (3769 seconds)
Published: Thu Mar 29 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.