Difference between revisions of "Javascript1"

From FreekiWiki
Jump to navigation Jump to search
(Added week3 demo code)
Line 548: Line 548:
  
 
===Week 3: Objects, Arrays, and Methods===
 
===Week 3: Objects, Arrays, and Methods===
 +
Under construction; watch this space...
  
 
====Objects====
 
====Objects====
Line 554: Line 555:
 
{| class="wikitable"
 
{| class="wikitable"
 
|+ Variables vs. Properties
 
|+ Variables vs. Properties
|-
+
!Variables...
|Variables...
+
!Properties...
|Properties...
 
 
|-
 
|-
 
| live in a global or function "scope" (execution context)
 
| live in a global or function "scope" (execution context)
Line 586: Line 586:
  
 
More operators:
 
More operators:
{| class="wikitable"
+
{| class="wikitable" style="text-align:center;"
|-
+
! operator
 +
! input type
 +
! example
 +
! result
 +
! result type
 
|-
 
|-
| .
+
|_._
 +
(dot)
 +
|OBJ,IDENT
 +
|obj.name
 +
|"Bubba"
 +
|any
 
|-
 
|-
| []
+
|_[_]
 +
(index/member/"sub")
 +
|OBJ,STR
 +
|obj["name"]
 +
|"Bubba"
 +
|any
 
|-
 
|-
| delete
+
| delete _._
 +
|OBJ,IDENT
 +
|delete obj.name
 +
|true
 +
| BOOL
 +
(true if found, else false)
 
|-
 
|-
| in
+
| _ in _
 +
|IDENT,OBJ
 +
|(name in obj)
 +
|true
 +
|BOOL
 
|}
 
|}
  
Line 610: Line 633:
 
** pop()
 
** pop()
 
** join()
 
** join()
 +
** many more...
 +
 +
====Demo Code====
  
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 0: sample from exercise #3'''
 +
<div class="mw-collapsible-content">
 +
//===== Version 0: Global functions with card argument (from Exercise #3)
 +
<br>
 +
function rank(cardnum) {
 +
    return Math.floor(cardnum/4)+1;// --> 1..13
 +
}
 +
function suit(cardnum) {
 +
    return cardnum%4+1; // --> 1..4
 +
}
 +
function color(cardnum) {
 +
    return (suit(cardnum)<3)? "red":"black";
 +
}
 +
//etc...
  
====Demo Code====
+
//Testing:
 +
rank(51); // 13 (King)
 +
suit(51); // 4 (Clubs)
 +
color(51); // "black"
 +
</div></div>
 +
 
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 1: adding card names'''
 +
<div class="mw-collapsible-content">
 +
//===== Version 1: Add card names
 +
<br>
 +
function rank(cardnum) {
 +
    return Math.floor(cardnum/4)+1;// --> 1..13
 +
}
 +
function suit(cardnum) {
 +
    return cardnum%4+1; // --> 1..4
 +
}
 +
function color(cardnum) {
 +
    return (suit(cardnum)<3)? "red":"black";
 +
}
 +
//etc...
 +
<br>
 +
function name(cardnum) {
 +
    return rankNames[rank(cardnum)] + " of " + suitNames[suit(cardnum)];
 +
}
 +
<br>
 +
var rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"];
 +
var suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
 +
 
 +
//Testing:
 +
rank(51); //13
 +
suit(51); //4
 +
color(51); // "black"
 +
name(51); // King of Clubs
 +
 
 +
</div></div>
 +
 
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 2a: single controller object'''
 +
<div class="mw-collapsible-content">
 +
//======== Version 2: Methods of single object
 +
var cardReader = {}; // "toolkit" object containing all card functions
 +
<br>
 +
cardReader.rank = function(cardnum) {
 +
    return Math.floor(cardnum/4)+1;// --> 1..13
 +
}
 +
cardReader.suit = function(cardnum) {
 +
    return cardnum%4+1; // --> 1..4
 +
}
 +
cardReader.color = function(cardnum) {
 +
    return (this.suit(cardnum)<3)? "red":"black";
 +
}
 +
<br>
 +
cardReader.name = function(cardnum) {
 +
    return this.rankNames[this.rank(cardnum)] +" of "+ this.suitNames[this.suit(cardnum)];
 +
}
 +
<br>
 +
cardReader.rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"];
 +
cardReader.suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
 +
 
 +
//Testing:
 +
cardReader.rank(51); //13
 +
cardReader.suit(51); //4
 +
cardReader.color(51); // "black"
 +
cardReader.name(51); // King of Clubs
 +
</div></div>
 +
 
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 2b: single controller object (alternate form)'''
 +
<div class="mw-collapsible-content">
 +
//======== Version 2b: Methods of single object (object literal/JSON form)
 +
var cardReader = { // "toolkit" object containing all card functions
 +
<br>
 +
rank: function(cardnum) {
 +
    return Math.floor(cardnum/4)+1;// --> 1..13
 +
},
 +
suit: function(cardnum) {
 +
    return cardnum%4+1; // --> 1..4
 +
},
 +
color: function(cardnum) {
 +
    return (this.suit(cardnum)<3)? "red":"black";
 +
},
 +
<br>
 +
name: function(cardnum) {
 +
    return this.rankNames[this.rank(cardnum)] +" of "+ this.suitNames[this.suit(cardnum)];
 +
},
 +
<br>
 +
rankNames: ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"],
 +
suitNames: ["","Hearts","Diamonds","Spades","Clubs"]
 +
}; //end cardReader
 +
 
 +
//Testing:
 +
cardReader.rank(51); //13
 +
cardReader.suit(51); //4
 +
cardReader.color(51); // "black"
 +
cardReader.name(51); // King of Clubs
 +
</div></div>
 +
 
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 3: single maker object, multiple instance objects'''
 +
<div class="mw-collapsible-content">
 +
//===== Version 3: Card as object (w. own methods & cached data fields)
 +
// Each card is now an object, created by function makeCard
 +
function makeCard(cardnum) {
 +
    var card = {};
 +
<br>
 +
    //computed initially:
 +
    card.rank = Math.floor(cardnum/4)+1;
 +
    card.suit = cardnum%4+1;
 +
<br>
 +
    //deferred:
 +
    card.color = function() {
 +
        return (this.suit<3)? "red":"black";
 +
    }
 +
<br>
 +
    card.name = function() {
 +
        return (rankNames[this.rank] +" of "+ suitNames[this.suit]);
 +
    }
 +
<br>
 +
    var rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"];
 +
    var suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
 +
<br> 
 +
    return card;
 +
}
 +
 
 +
//Testing:
 +
var card51 = makeCard(51);
 +
card51.rank; //13
 +
card51.suit; //4
 +
card51.color(); //"black"
 +
card51.name(); //King of Clubs
 +
</div></div>
 +
 
 +
 
 +
<div class="toccolours mw-collapsible mw-collapsed">
 +
'''Version 4: multiple instance objects sharing arrays'''
 +
<div class="mw-collapsible-content">
 +
//===== Version 4: Card as object (as before), but arrays are shared
 +
<br>
 +
function makeCard(cardnum) {
 +
    var card = {};
 +
<br>
 +
    //computed initially:
 +
    card.rank = Math.floor(cardnum/4)+1;
 +
    card.suit = cardnum%4+1;
 +
<br>
 +
    //deferred:
 +
    card.color = function() {
 +
        return (this.suit<3)? "red":"black";
 +
    }
 +
<br>
 +
    card.name = function() {
 +
        return (makeCard.rankNames[this.rank] +" of "+ makeCard.suitNames[this.suit]);
 +
    }
 +
<br>   
 +
    return card;
 +
}
 +
<br>
 +
//Arrays created AFTER function, attached to it:
 +
makeCard.rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"];
 +
makeCard.suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
  
 +
//Testing:
 +
var card51 = makeCard(51);
 +
card51.rank; //13
 +
card51.suit; //4
 +
card51.color(); //"black"
 +
card51.name(); //King of Clubs
 +
</div></div>
  
 +
<!--
 
====Exercises====
 
====Exercises====
 
'''1)''' Rewrite your playing-card toolbox (see Week #2, Exercise #3) using an object to represent each card.  Use the same numbering system as before (card #0= Ace of Hearts, #51=King of Clubs).
 
'''1)''' Rewrite your playing-card toolbox (see Week #2, Exercise #3) using an object to represent each card.  Use the same numbering system as before (card #0= Ace of Hearts, #51=King of Clubs).
  
 
Specifically, write a function ''makeCard(cardID)'' which returns an object representing the card of that ID.  Each card object should store its own ID as a value-property, and also have a method for each of the functions from before.  Because each card knows its ID, each of its methods will need fewer parameters than the original function.
 
Specifically, write a function ''makeCard(cardID)'' which returns an object representing the card of that ID.  Each card object should store its own ID as a value-property, and also have a method for each of the functions from before.  Because each card knows its ID, each of its methods will need fewer parameters than the original function.
 +
-->
  
 
===Week 4: Constructors, Prototypes, and Inheritance===
 
===Week 4: Constructors, Prototypes, and Inheritance===

Revision as of 02:13, 19 November 2013


General Information

This course is currently running November-December 2013, Tuesdays 11:30-1:30.

Part 1 (November) will offer students a solid foundation in Javascript as a general-purpose programming language. Part 2 (December) will explore Javascript's integration in web browsers with HTML, CSS, and the Document Object Model (DOM).

Instructor: Dan Bauer (email: dsbauer at gmail)

Course Outline

Week 1: Values and Expressions

  • Firebug Console/Interpreter
    • The console allows a dialogue with Javascript interpreter: you make one (possibly compound) statement, it replies with one value.
  • Expressions
    • An expression (EXPR) can be:
      • a primitive (e.g. 1)
      • a variable (e.g. x)
      • an operator combining smaller EXPR's (e.g. x+1, 2*(x+1))
  • Operators have:
    • a keyword or symbol (OP)
    • a syntax template (e.g. _ OP _)
      • unary prefix: OP_
      • unary postfix: _OP
      • binary infix: _OP_
      • ternary infix: _OP_OP_
    • one or more inputs _ ("operands")
    • one output ("return value")
      • may be undefined
    • possible side-effects (e.g. change in variable's value)
  • Variables have:
    • a name/identifier
    • a value (initially undefined)
      • each value has a type (primitive or reference)
    • a scope
  • Other (non-expression) Statements
    • var NAME;
    • var NAME = EXPR;
    • if (EXPR) {EXPR;}
    • if (EXPR) {EXPR;} else {EXPR;}
  • Primitive Types
    • undefined
    • Number
      • same type for integers and floats (fractional)
      • special values: NaN ("not a number"), Infinity
    • String
      • wrapped in either " " or ' '
      • may contain opposite quote or other special characters
        • \t (tab)
        • \n (newline)
      • may be empty ("")
    • Boolean (true/false)
      • false-ish values: false,undefined,null,0,"",NaN
      • (some) true-ish values: true,1,"false","undefined","0",{} (empty object)

Some Sample Operators:

operator input type example result result type side effects
typeof NUM typeof 1 "number" STR
STR typeof "word" "string"
BOOL typeof true "boolean"
,

(sequence)

any "a", "b", "c" "c" type of

last value

(4,"3"),("two",1) 1
+

(plus)

NUM 1+1 2 NUM
+

(concatenate)

STR "1"+"1" "11" STR
mixed 1+"2" "12" STR
- * / % NUM 3-1 2 NUM
STR "3"-"1" 2
mixed "3"-1 2
< > <= >=

(comparison)

NUM 1<2 true BOOL
STR "b"<"a" false
==

(equality)

NUM 1==2 false BOOL
STR "a"=="aa" false
mixed 1=="1" true
mixed 0==false true
===

(identity)

NUM 1===2 false BOOL
STR "abc"==="abc" true
mixed 1==="1" false
mixed 1===true false
!

(not)

any !1 false BOOL
!"" true
&&

(and)

any null && "red" null first false-ish

or last input

1 && "green" "green"
||

(or)

any "yes" || null "yes" first true-ish

or last input

"" || 0 0
?:

(conditional)

any true? "yes": "no" "yes" any
variable assignment operators x is now...
=

(assignment)

any x=1 1 same as input 1
x = "blue" "blue" "blue"
+=

(incremental assignment)

NUM x=0; x+=2; 2 NUM 2
STR x="he"; x+="llo"; "hello" STR "hello"
mixed x=""; x+=2; "2" STR "2"
++

(post-increment)

NUM x=0; x++; 0 NUM 1
STR x=""; x++; 0 1
++

(pre-increment)

NUM x=0; ++x; 1 NUM 1
STR x=""; ++x; 1 1

Week 2: Loops and Functions

Nov12 in-class scratchpad

Loops have:

  • some form of counter ("iterator"), a variable which changes with each cycle of the loop
  • an initialization (INIT)
  • a counter increment (CHANGE)
  • a repeated ACTION
  • a continuation condition (COND)
    • any COND expression will be treated as a Boolean, either true-ish or false-ish
    • the ACTIONs and CHANGE occur only when COND is true-ish

Loop Statements:

Loop keyword Pattern Example
while
 INIT;
 while(COND) {
   ACTION;
   ...
   CHANGE;
 }
 var i=0;
 while (i<10) {
   alert(i);
   i++;
 }
for
 for (INIT; COND; CHANGE) {
   ACTION;
   ...
 }
 for (var i=0; i<10; i++) {
  alert(i);
 }
  • Sometimes the COND includes the CHANGE, e.g.:
 for (var i=0; (i++)<10; ) {...}
 for (var i=10; --i; ) {...}
  • ACTIONs can be any statements, including nested loops

Functions:

  • are mini-programs, independent modules which can be reused in multiple contexts
  • are a kind of Object, which can be referenced by multiple names
  • have parameters which can change for each call/use
  • return one value of any type (or undefined if unspecified)
    • the keyword return specifies the returned value and exits the function immediately
  • create a separate space ("call object","execution context", or "scope") for their local variables and parameters
    • Each call creates a separate scope.
    • Scopes last as long as needed, then destroyed automatically.

Function-specific Operators:

operator input type example result result type side effects
 function NAME(PARAMS){BODY}
 function(PARAMS){BODY}

(define function)

function add(x,y) {return x+y;} a function Function creates Function object,

creates (or redefines) var. NAME if included

 NAME(ARGS)

(call function)

NAME: Function,

ARGS: any

add(1,2) 3 any depends on function body

Exercises

1) Write a function to calculate, for a group of N people where everyone shakes the hand of everyone else, how many total handshakes there are.

Solution...

function numPairs(setSize) {
   return setSize*(setSize-1)/2;
}

Write another function to enumerate these interactions, returning a single string describing them all. People may be identified by number. For example, for N=3, it might return: "#1 meets #2. #1 meets #3. #2 meets #3."
(Hint: you may want a second "helper" function to handle a single interaction.)

Solution...

function writePair(personA,personB) {
   return "#"+personA+" meets #"+personB+".  ";
}
function enumeratePairs(numPeople) {
   var result="";
   for (var personA=1; personA<=numPeople; personA++) {
       for (var personB=personA+1; personB<=numPeople; personB++) {
           result+=writePair(personA,personB);
       }
   }
   return result;
}

2) Write a function to decide whether a given integer is prime. You may need some of these functions/operators:

  • function Math.floor(N): truncates any fractional part of a number N (i.e. returns greatest int <=N)
  • function Number.isInteger(N): returns true is N is an integer
  • modulo operator %: x%y returns 0 if x divides evenly by y

Solution...

function isPrime(n) {
   if (n==0 || n==1 || !Number.isInteger(n))
       return false;    // excludes 0,1,and non-integers
   // search for number which divides n evenly...
   var sqrt=Math.sqrt(n); // only need to search up to n's square root
   for (var test=2; test<=sqrt; test++) {
       if (Number.isInteger(n/test))
           return false;  //found one; n isn't prime
   }
   return true;//n must be prime
}

3) Imagine that a deck of playing cards is sorted by rank and suit: first all the Aces, then the Twos, etc, with the Kings last. Within each rank, the suits are in the order Heart, Diamond, Spade, Club. Number each card in order from 0 to 51 (i.e. 0=Ace of Hearts; 51=King of Clubs), and let that ID number represent the corresponding card.

Following that encoding scheme, write a set of functions to compute different features/relations of the cards:

  • rank(card) returns 1-13, representing the card's rank.
  • suit(card) returns 1-4, representing the card's suit.
  • cardNum(rank,suit) returns 0-51, identifying the card of a given rank and suit.
  • color(card) returns "red" or "black".
  • precedes(cardA,cardB) returns true only if cardA is one less in rank than cardB. Assume rank wrap-around (King precedes Ace precedes Two).
  • sameColor(cardA,cardB) returns true only if cardA and cardB have the same color.
  • nextInSuit(cardA) returns cardB, the ID number of the card following cardA in the same suit. Assume wrap-around.
  • prevInSuit(cardB) returns cardA, the ID number of the card preceding cardB in the same suit.

Your functions may call each other. Try to reuse their functionality to avoid duplicating code.

Initially, assume each function is given valid arguments (i.e. the args are integers in the appropriate range). Later, devise a system for dealing with arguments which are invalid in various ways, and rewrite your functions to tolerate such errors whenever possible.

Solution: simple version...

function rank(card) { // --> 1..13
   return Math.floor(card/4)+1;
}
function suit(card) { // --> 1..4
   return (card%4)+1;
}
function cardNum(rank,suit) { // --> 0..51
   return (rank-1)*4 + (suit-1);
}
function color(card) { // -->"red,"black"
   var theSuit=suit(card);
   return (theSuit<3)? "red": "black";
}
function precedes(cardA,cardB) { //-->false,true
   var diff= rank(cardB)-rank(cardA);
   return diff==1 || diff==-12;
}
function sameColor(cardA,cardB) { //-->false,true
   return color(cardA)==color(cardB);
}
function nextInSuit(cardA) {//--> 0..51
   nextCard = cardA+4;
   if (nextCard>51) nextCard-=52;
   return nextCard;
}
function prevInSuit(cardB) {//--> 0..51
   prevCard = cardB-4;
   if (prevCard<0) prevCard+=52;
   return prevCard;
}

Solution: error-detecting version...

// Helper function:
function isValid(num,low,high) { // Returns--> NaN, true
   if ((typeof num)!="number") //wrong type
       return NaN;
   if (!Number.isInteger(num)) //non-integer
       return NaN;
   if (num<low || num>high) //out of range
       return NaN;
   return true;
}
function rank(card) { // --> 1..13, NaN
   return isValid(card,0,51) &&
       Math.floor(card/4)+1;
}
function suit(card) { // --> 1..4, NaN
   return isValid(card,0,51) &&
       (card%4)+1;
}
function cardNum(rank,suit) { // --> 0..51, NaN
   return isValid(rank,1,13) &&
           isValid(suit,1,4) &&
           ((rank-1)*4 + (suit-1));
}
function color(card) { // -->"red,"black",NaN
   var theSuit=suit(card);
   if (isNaN(theSuit))
       return NaN;
   return (theSuit<3)? "red": "black";
}
function precedes(cardA,cardB) { //-->false,true,NaN
   var diff= rank(cardB)-rank(cardA);
   if (isNaN(diff))
       return NaN;
   return diff==1 || diff==-12;
}
function sameColor(cardA,cardB) { //-->false,true,NaN
   var colorA=color(cardA), colorB=color(cardB);
   if (Number.isNaN(colorA) || Number.isNaN(colorB))
       // must use Number.isNaN() instead of isNaN(), which returns true for non-numeric strings
       return NaN;
   return colorA==colorB;
}
function nextInSuit(cardA) {//--> 0..51,NaN
   nextCard = isValid(cardA,0,51) && cardA+4;
   if (nextCard>51) nextCard-=52;
   return nextCard;
}
function prevInSuit(cardB) {//--> 0..51,NaN
   prevCard = isValid(cardB,0,51) && cardB-4;
   if (prevCard<0) prevCard+=52;
   return prevCard;
}

Week 3: Objects, Arrays, and Methods

Under construction; watch this space...

Objects

An object is a collection of named "properties" or "members", similar to variables...

Variables vs. Properties
Variables... Properties...
live in a global or function "scope" (execution context) live in an object
need no prefix are (usually) prefixed with their object and an operator (. or [])
must be declared with var are created merely by assigment
cause an error if not declared return undefined if not declared
have naming restrictions may be named with any string
last until their scope expires may be deleted

Methods:

  • are functions which are properties of an object.
  • use the keyword this to refer to their object (not themselves)
  • Examples:
    • Math.sqrt()
    • Math.floor()
    • Number.isInteger()

More operators:

operator input type example result result type
_._

(dot)

OBJ,IDENT obj.name "Bubba" any
_[_]

(index/member/"sub")

OBJ,STR obj["name"] "Bubba" any
delete _._ OBJ,IDENT delete obj.name true BOOL

(true if found, else false)

_ in _ IDENT,OBJ (name in obj) true BOOL

Arrays

An array is an object with a series of integer-indexed values.

A "pseudo-array":

  • is any object with some properties named by integers

A real Array is a special class of object...

  • which automatically coordinates its integer properties with a special length property
  • which has a predefined set of useful methods:
    • push()
    • pop()
    • join()
    • many more...

Demo Code

Version 0: sample from exercise #3

//===== Version 0: Global functions with card argument (from Exercise #3)

function rank(cardnum) { return Math.floor(cardnum/4)+1;// --> 1..13 } function suit(cardnum) { return cardnum%4+1; // --> 1..4 } function color(cardnum) { return (suit(cardnum)<3)? "red":"black"; } //etc...
//Testing:
rank(51); // 13 (King)
suit(51); // 4 (Clubs)
color(51); // "black"


Version 1: adding card names

//===== Version 1: Add card names

function rank(cardnum) { return Math.floor(cardnum/4)+1;// --> 1..13 } function suit(cardnum) { return cardnum%4+1; // --> 1..4 } function color(cardnum) { return (suit(cardnum)<3)? "red":"black"; } //etc...
function name(cardnum) { return rankNames[rank(cardnum)] + " of " + suitNames[suit(cardnum)]; }
var rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"]; var suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
//Testing:
rank(51); //13
suit(51); //4
color(51); // "black"
name(51); // King of Clubs


Version 2a: single controller object

//======== Version 2: Methods of single object
var cardReader = {}; // "toolkit" object containing all card functions

cardReader.rank = function(cardnum) { return Math.floor(cardnum/4)+1;// --> 1..13 } cardReader.suit = function(cardnum) { return cardnum%4+1; // --> 1..4 } cardReader.color = function(cardnum) { return (this.suit(cardnum)<3)? "red":"black"; }
cardReader.name = function(cardnum) { return this.rankNames[this.rank(cardnum)] +" of "+ this.suitNames[this.suit(cardnum)]; }
cardReader.rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"]; cardReader.suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
//Testing:
cardReader.rank(51); //13
cardReader.suit(51); //4
cardReader.color(51); // "black"
cardReader.name(51); // King of Clubs


Version 2b: single controller object (alternate form)

//======== Version 2b: Methods of single object (object literal/JSON form)
var cardReader = { // "toolkit" object containing all card functions

rank: function(cardnum) { return Math.floor(cardnum/4)+1;// --> 1..13 }, suit: function(cardnum) { return cardnum%4+1; // --> 1..4 }, color: function(cardnum) { return (this.suit(cardnum)<3)? "red":"black"; },
name: function(cardnum) { return this.rankNames[this.rank(cardnum)] +" of "+ this.suitNames[this.suit(cardnum)]; },
rankNames: ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"], suitNames: ["","Hearts","Diamonds","Spades","Clubs"] }; //end cardReader
//Testing:
cardReader.rank(51); //13
cardReader.suit(51); //4
cardReader.color(51); // "black"
cardReader.name(51); // King of Clubs


Version 3: single maker object, multiple instance objects

//===== Version 3: Card as object (w. own methods & cached data fields)
// Each card is now an object, created by function makeCard
function makeCard(cardnum) {
   var card = {};

//computed initially: card.rank = Math.floor(cardnum/4)+1; card.suit = cardnum%4+1;
//deferred: card.color = function() { return (this.suit<3)? "red":"black"; }
card.name = function() { return (rankNames[this.rank] +" of "+ suitNames[this.suit]); }
var rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"]; var suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
return card; }
//Testing:
var card51 = makeCard(51);
card51.rank; //13
card51.suit; //4
card51.color(); //"black"
card51.name(); //King of Clubs


Version 4: multiple instance objects sharing arrays

//===== Version 4: Card as object (as before), but arrays are shared

function makeCard(cardnum) { var card = {};
//computed initially: card.rank = Math.floor(cardnum/4)+1; card.suit = cardnum%4+1;
//deferred: card.color = function() { return (this.suit<3)? "red":"black"; }
card.name = function() { return (makeCard.rankNames[this.rank] +" of "+ makeCard.suitNames[this.suit]); }
return card; }
//Arrays created AFTER function, attached to it: makeCard.rankNames = ["","Ace","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"]; makeCard.suitNames = ["","Hearts","Diamonds","Spades","Clubs"];
//Testing:
var card51 = makeCard(51);
card51.rank; //13
card51.suit; //4
card51.color(); //"black"
card51.name(); //King of Clubs


Week 4: Constructors, Prototypes, and Inheritance

Sample Code

Nov12 in-class scratchpad