JSNotes5 – the DOM



JSNotes5 –Objects and the DOM v6 2/01/2021Note on Passing ParametersPrimitive types such as numbers, strings and booleans are passed as values to functions. That is, a distinct copy of the value is made and passed to the function and any changes which the function makes to the copy it got does not affect the original. Likewise if a new variable gets assigned the value, they are distinct copies of that value. For example if we write a=7; b=a; a=10; then b still has the value 7.Finally when variables of primitive types are compared it is their values which are compared.Arrays, Dates and other Objects (but not Strings) are reference types and are passed by reference. That is, when an array is passed to a function that function gets access to all the values in the arrays and changes which that function makes to the array persist after the function ends. Similarly, if we write a=new Array[5,10]; b=a; a[0]=2; then b[0] will also be 2.That is because a and b refer to the same array. If we want b to be a separate copy of a then we must make a deep copy (entry by entry). Finally if, in the example above, we test a==b then we are testing to see if a and b refer to the same array ---- and we are not testing to see if they have the same values! If we write aa=new Array[5,10]; bb=new Array[5,10]; then aa==ba will be false, even tho’ they have the same values, but in the example in the previous paragraph our test a==b will be true (because for primitive data types we are seeing if the values are equal, but for objects and such we are seeing if the locations in memory are equal.Here is an example which illustrates the difference between pass by value and pass by reference: The code: Please notice that myStr is a global variable of a primitive type.myStr = 'my';? ?function yup(){? ?myStr +="!";? ? //concatenates an exclamation point at the end of myStr? ?console.log("in yup ", myStr);}function loc(x){? x += "#";? console.log("in loc ", myStr, "and x is ", x);}console.log(myStr); // myyup();console.log(myStr); //in yup my!loc(myStr); //in loc my! and x is my!#console.log(myStr); //my! What happened here?In yup() we accessed the global variable myStr and appended an "!" to it.In loc() we had a parameter, which we called with myStr as the argument. You can see that the "#" was appended to x, the local variable, but that myStr was not changed – and the last console.log shows that myStr was not changed when we finished loc(). In other words, what loc() got was a copy of myStr, or its value.Now contrast that with what happens when we deal with arrays.Arrays are 'pass by reference" which means that the function is told where the array is stored in memory and can change what is in the array.The code: Please notice that myArr is also a global variable, but not a primitive data type.The (2) before logging an array denotes that we are looking at an arraymyArr = [0, 1];console.log(myArr); //(2) [0,1]function yup(){? myArr[1]=7;?console.log("in yup ", myArr);}function loc(A){? ?A[0]=5;? ?console.log("in loc ", A, " and myArr is ", myArr);}yup(); //in yup (2)[0, 7]console.log("after yup ", myArr); //after yup (2) [0,7]loc(myArr); // in loc ?(2)?[5, 7] ?and myArr is ?(2)?[5, 7]console.log("after loc ", myArr); // after loc (2) [5, 7]What happened here? In this code yup() changed a global variable and that changed persisted after the function finished executing – just as it did with our myStr example.But something rather different happened in the loc() function. In each case we passed a global variable to the function --- but since myStr was passed by value there was no change to the global variable when we changed the parameter. On the other hand, myArr was passed by reference, so that when we changed an entry in A we actually changed the global variable. And as you can see that change persisted after loc() finished executing.MORAL: Arrays and Objects are passed by reference which means that the function gets a hold of the actual array or object passed to it and can make changes in it!! Strings, Numbers and Booleans are passed by ment: In some languages strings are also passed by reference – but not in JS!Strings are immutable – that is once you define a string you can not change any of its characters. So, it doesn’t matter how they are copied and passed because they can’t be changed. You can, however, concatenate more characters onto its end – see above and immutableStrings.html in Basic_JavaScript_Programs_Part_B.As explained at when your code looks like it is changing the value of a string, what is really happening is that a new string is being created and the variable (name of the old string) is being made to point to the new string.When you compare two strings you are comparing their values – because they are primitive data types.ObjectsIn JavaScript there are three kinds of objectsNative objects such as Math and Date, and Array. You have already met some of the Math object's methods, e.g. Math.round() and Math.random().Host objects which are provided by the browser. These are introduced when discuss the DOM or Document Object Model.Custom or user-defined objects which are ones you create and are described below.It is customary to capitalize the names of objects in JavaScript.Before starting on custom objects, let us cement our understanding of objects by looking a bit more at arrays:ArraysInstantiating arrays (getting an instance of a new array)There are several ways for you to define a new array:Define an array by listing its members A = [1,3,5];Fruits =[‘apple’, banana’, ‘pear’];Diag = [ [1, 0] , [0, 2] ];Define an array as an Array (using the Array() constructor function and the reserved word new) , and list the membersA = new Array(1, 3, 5);Fruits = new Array(‘apple’, ‘pear’);Diag = new Array(column1, column2); column1= new Array(1, 0); column2 = newArray (0,2);Define the array (with or without its length) and assign values to the elementsA = new Array( ); A[0]=1; A[1]=3; A[6]=5; //some entries in A are undefinedFruits= new Array(2); Fruits[0]=’apple’; Fruits[1]=’pear’;What do you get when you define a new array and what are these notations about?In JavaScript every object is defined by a function which has the same name as the class (type of object.). For example, the Array( ) function is used to create a new Array object, the Date( ) function is used to create a new Date object, etc.You will see this below when the way you declare an object of your own design (a custom object) is by defining a function.These functions are often referred to as constructors.NOTE: The first method above for instantiating A is an abbreviation.The constructor function sets up the attributes and methods for your custom object, but it doesn't create an actual instance (example) of that object. You will create an instance of the object by using the constructor.In order to tell the JavaScript parser a heads-up that you want a new instance of some object you use the reserved word new: A = new Array( );When you pass no paramete;r to the constructor you get default values.For example, d1=new Date( ) returns today’s date; A=new Array( ) ; returns an empty array.When you pass values to the constructor, those values are used to instantiate your object.For example, when you write A = new Array(1, 3, 5); you are passing the parameters 1, 3 and 5 to the Array( ) constructor and it is using those values to build A. The constructor (which is a function) returns a reference to the array it built.So when you write A= new Array(1, 3, 5) you are calling the Array ( ) constructor and assigning the value it returns to the variable A --- same as you do with any function.How does the constructor do it – or this is magicEvery object comes with an attribute named this which refers to the object itself.You will see how this is used when we talk about custom objects.An array has some built in attributes, e.g. length, and built in methods, e.g. sort( )If A is an array, then A.length is its length and A.sort( ) is the sort method.Can I add more methods and properties? YesYou use the prototype property described for custom objects below.Arrays come with a number of built in methods. Push and pop add and remove entries at the end; shift and unshift work at the beginning (0-index). Pop and shift return the removed element. You can also concatenate one array on to the end of another .Perhaps the nicest thing of all is the ability to simply add elements, including skipping spaces. Consider (Chrome’s responses are in blue) A = [1, 2](2)?[1, 2]console.log(A)VM136:1 (2)?[1, 2]undefinedA[4]=1010console.log(A)VM220:1 (5)?[1, 2, empty × 2, 10] //Chrome notes 2 empty spacesAssociative arrays’Whats this about “associative arrays”? It is possible to have an array which is indexed by identifiers (names) rather than numbers. Such things are called associative arrays or, in some languages, hashes or (in Python) dictionaries.We will use them extensively when we talk about images, the DOM and forms, and, of course, they are also how we define objects.It is common to describe an associative array as name-value or key-value pairs. In the example below, the first key is “laundry” and its value is “Monday”.Example: Days = new Object( ); Days["laundry"] = “Monday”; Days['groceries'] = “Friday” Days.fun= “Saturday” document.write(“My favorite day is “+Days[“fun”] +”!,br />”);Days should defined as a new Object, not a new Array – Days is an associative array, which is why the [ ] notation is used.There is even a for (each) function which will index thru an associative array.But as you can also see (in the "fun" line) we can access members of an associative array using dot notation.Objects are actually a collection of key-value pairs. The key gives the name of the property or method, and the value is what is assigned to it. There are several ways to set and get values in an object. If we have the objects Days as above then the following are equivalent: Days['laundry'] Days.laundryWe can create a new object with either an object literal or from a constructor functions:With an object literal: let myTown = {city: "Boston", state: "MA" }With a constructor function: function Place(city, state) { this.city = city; this.state = state } let myTown = new Place("Boston", "MA");The obvious advantage of the constructor approach is that you can make more objects which use that constructor. For this simple example, it may not matter, but if our object had more properites and complicated methods, then we wouldn't want to be typing the code in over and over.Another advantage of the constructor approach is that now Place is an object which may be extended ---- for example an Address object might extend it.And we already saw how ColoredPoint would extend Point.An object may have methods and properties – as we saw in the Point example.Every object has a prototype and a property this.The prototype is like the blue print for the object, and we saw in the Point- ColoredPoint example that we may use the prototype for Point to write the constructor function for Colored Point.We also saw that this points to the object that we are working with (i.e. are creating.) There is an Object object which every other object inherits from.This great Object in the sky has some methods and attributes, Any custom object will inherit them. For example, Object.keys(myObject) is an array of all the keys (names) in myObject, Object.values(myObject) is the obvious array and Object.create(myObject) is a method used to make new objects based on the current one. This is pretty advanced stuff and we will not be using it.Every function is an object When we have a constructor function (and notice that contructors do not have a return statement) that function uses the default of returning 'this' – i.e. a pointer to the object it just created.Of course, as with any function, if we want to grab a hold of the value that function just returned (as we surely do with constructors) we assign the value being returned to a variable: let myTown = new Place("Boston", "MA");Because a function is an object it may have its own properties and methods.In the Point example we saw how the show method could be defined either inside the code for Point() or it could be set to a previously defined function.Because a function is an object it may be passed into another function as a parameter. This happens all the time with callback functions. We will look at this more in the VoiceThreads.Because a function is an object, it may be something which is returned by another function. This will give us a closure – again we will talk about this more in the VoiceThreads.All these items together are what JavaScript developers mean when they say "Functions are first class objects in JavaScript."The value of 'this' depends on where the function is called from. That last sentence is the heart of the mistakes that people make when working with closures and 'this'. We will spend a lot of time discussing this issue when we discuss closures. Stay tuned.Excellent but sophisticated references on objects are at and and Custom objects and prototypeIn JavaScript there are lots of objects (e.g. Arrays, Strings, etc.) Each of these is a specialization of the general Object. Now, JavaScript is prototype-based object oriented. See and and and the links at the bottom of each.With any object (including the native object such as Array or String) you may add additional properties and methods. You do this through the object’s constructor or prototype. You should not do it with the built in objects – this example is only for teaching.As an example, if my Strings are credit card numbers I might want all my Strings to have a verification code. I can add this property to all strings as follows:String.prototype.veri=’ ‘Notice that I must capitalize String (the name of object).As another example, if all my strings are to be centered on a space 72 characters wide, I might want a method which calculates the number of spaces to the left of the first letter. I can do this as follows: function leftSpace() {spBlank=72-this.length; return Math.round(spBlank/2) } String.prototype.spacesToLeave=leftSpace; Notice that we have defined a function and then made it a method for the String object.We may also attach properties and methods to objects we have defined ourselves. Let us look at the three Custom Object pages. Please note that the way you define an object is by defining its constructor (a function). function MyObject(param1, param2, param3) {this.property1=param1; this.property2=param2; this.property3=param3; }I can then instantiate such an object with myO= new MyObject(5,3,2)If I prefer I can also add methods to the definition of MyObject:function MyObject(param1, param2, param3) {this.property1=param1; this.property2=param2; this.property3=param3; this.showOff=function() { some code } }After I instantiate myO as above I may refer to myO.showoff()If I had neglected to define MyObject.showOff() before I can add it by sayingMyObject.prototype.showOff = function() { some code } orMyObject.prototype.showOff =nameOf Previously Defined FunctionI can use prototype to add a method as above – or I can include it in the constructor. function MyObject(para1, param2, param3) {this.property1=param1; this.property2=param2; this.property3=param3; this.myFunc=nameOfPreviouslyDefinedFunction; }this is a reserved word which refers to the object you are in.After I instantiate myO as above I may refer to myO.myFunc()An object may also be viewed as an associative array of property attributes and values.For example, suppose I define function Triangle(s1, s2, s3) {this.side1=s1; this.side2=s2; this.side3=s3; }And suppose we have a triangle bigT =new Triangle(10,15,15) ; Now I can refer to the sides of bigT as bigT.side1, bigT.side2 etc. or as bigT[“side1”] bigT[“side2”] etc.Notice that in using this associative (name-value pairs) format, the name of the property (side1 etc.) is a string and hence is in quotes. This allows me to write code like: for (i=1; i<4;i++) {document.write(“Side number ” +i+” has length “+bigT[“side”+i]+<br /.)};Some comments on the syntax:Inside the constructor function: We are assigning values to properties, so we use an = sign. We are writing JavaScript, so we signal the end of a statement with a semicolon.In the object literal notation We use the : between the name (key) and the value We signal the end of a name-value pair with a comma.When we assign a previously defined function to a property inside a constructor we use the name of the function, but we do not use the () --- which would cause the designated function to execute and then it value it returned is what would be assigned. Example: Suppose many of my favorite objects have a name property. I might define a function: function sayHi() {alert("Hello there, ",this.name, " ! How are you today?");}Inside the constructor for Pet I could write this.hi = sayHi; //NOTE – no () after sayHIThe complete code is:function sayHi() {alert("Hello there, ",this.name, " ! How are you today?");}function Pet(x) { this.name = x; this.hi = sayHi; //No parens after sayHi- we don't want execution}fido = new Pet("Fido");fido.hi(); // Note parens to get the function to execute/Odd habitsMany developers with use the same identifier for the parameter which is passed in and the property which is being set up – for example:function Pet(name) { this.name = name; this.hi = sayHi; //No parens after sayHi- we don't want execution}I don't love this custom b/c it confuses two things, but it is very common – in fact so common that there is even a short cut way to make the assignments --- another time. ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download