Notes for CodeSchool's Javascript Best Practices

The following are my notes for Codeschool.com Java Script Best Practices course: http://campus.codeschool.com/courses/javascript-best-practices/contents . The coarse mainly features how to create modules from your javascript code, in a way that is easy to manage. (Please also see the attached file for better formatting.)


JavaScript Best Practices

* notes 1.1

TERNARY CONDITIONALS

standard conditional
if (TRUE) {
i=1
} else {
i=2
}

ternary conditional
j==2 ? i=1 ; i=2;
i = true ? 1 : 2;

boolean
any value not false is considered true

compound boolean expressions can be used in ternary decisions

ternaries provide a format for picking immediately invoking functions
to immediately invoke a function you add parentheses after expression
function() {alert "Tim";}();

multiple actions can occur in each ternary result (but it is not suggested)
(expression == true) ? (i=1, j=2) : (i=2, j=1);

ternaries can be nested

* challenge 1.2

The above ternary conditional will assign 'no' to the adventureTime variable.

* challenge 1.3

The ternary expression above will assign 'yes' to the adventureTime variable.

* challenge 1.4

'Adventure time is now!'

* challenge 1.5

character = isHero ? 'Dhuun' : 'Pesky Gnat';

* challenge 1.6

Your new ternary expression will assign 'Dhuun' to the character variable.

* notes 1.7

LOGICAL ASSIGNMENT 1: THE "OR" OPERATOR

the OR operator "||" can be used in assignments
the first non-false value will be used
var name = inputName || 'unknown';
if the first value is used the 2nd is never evaluated
this is called a short-circuit
if no true value exists, last false value will be used

some false values are:
"", false, 0, undefined

* challenge 1.8

After this execution, the value of lost will be 4.

* challenge 1.9

Reflecting on this assignment for a bit, you realize that the undefined value will never even be examined. The name for this phenomenon in logical evaluation is called short-circuit.

* challenge 1.10

The variable lost will be set to the value of true.

* challenge 1.11

var pocketStuff = ['Dragon Tooth', 'Adventure Diary', 'Silver Tiger Coin'];
var pocketContents = pocketStuff || [];

* challenge 1.12

var pocketStuff = ['Dragon Tooth', 'Adventure Diary', 'Silver Tiger Coin'];
var cluesToThePast = pocketStuff || [];
getMyIdentity(cluesToThePast);

function getMyIdentity(memories) {
var identity = (memories.indexOf('Adventure Diary') >= 0) ? 'The One Who Learns' : undefined;
return identity || 'unknown';
}

* notes 1.13

LOGICAL ASSIGNMENT 2: THE "AND" OPERATOR

the '&&' operator uses the first false value or last true
var name = inputName && "trueValue";
the short circuit happens on first false value

some false values are:
"", false, 0, undefined

'and' is useful in contingent conditions
var knight = true;
var weapon = knight && "katana";

array.indexOf('data')
examines array and returns first occurrence of data
if the data is not found, -1 is returned

array.splice(index, numToRemove)
removes numToRemove strating at index to remove cells from the array
returns an array of removed cells

logicall assignments can be strung together
var armoryOpen = false;
var knight = true;
var weapon = knight && armoryOpen && "katana"; => would return false

* challenges 1.14

var beginJourney = aiedraIsConvincing && dhuunIsCurious;

* challenges 1.15

var surviveThisTrial = strength && !(fear);

* challenges 1.16

var strength = true;
var fear = false;
var pack = {
food: [ 'carrot',
'mystery meat',
'apple',
'crust of bread',
'spicy dried sausage',
'carrot',
'wedge of sharp cheese',
'jug of milk',
'mystery meat',
'carrot'
],
addFood: function(foodItem) {
this.food = this.food || [];
this.food.push(foodItem);
},
enoughFood: function(amount) {
return(this.food.length >= amount);
}
};

var surviveThisTrial = strength && !fear && pack.enoughFood(10);

console.log(surviveThisTrial);

* challenges 1.17

In the end, will you survive the trial at hand? (yes or no) yes

* challenges 1.18

The fear variable will short-circuit the logical assignment, and enoughFood will not be called at all.

* notes 1.19

THE SWITCH BLOCK

allows taking action on non boolean values

switch (variable) {
case 1:
food = "rabbit";
break; the keyword break exits the switch block
case 2: w/o break fall-through will continue to next case
case 3:
food = "squirrel";
break;
case 'red': can be any sort of value to check
food = "snake";
break;
default:
food = "none";
}

once a case is matched, all other cases are run
this is called fall-through unless a break statement is hit

* challenge 1.20

She said none of these.

* challenge 1.21

function aiedrasMutterings(lampsLit) {
var aiedrasWords;
switch (lampsLit) {
case 1: aiedrasWords = 'Darkness, there is so much darkness still shrouding the land.';
case 2: aiedrasWords = 'A beacon of hope, these two lamps are, but two more still await.';
case 3: aiedrasWords = 'Nearly it is complete, twilight breaking, is that a song I hear?';
case 4: aiedrasWords = 'It is done, a new age has begun, a new dawn has risen.';
default: aiedrasWords = 'Shall we live in Infinite Midnight always?';
}
return aiedrasWords;
}
alert(aiedrasMutterings(0));

* challenge 1.22

'Shall we live in Infinite Midnight always?'

* challenge 1.23

function sansTemple(direction) {
var happensNext;
switch (direction) {
case 'right hallway': happensNext = 'You find a door, it is locked. You head back from where you came.';
break;
case 'left hallway': happensNext = 'You find a door, it is locked. You head back from where you came.';
break;
case 'forward hallway': happensNext = 'You find a door, it is locked. You head back from where you came.';
break;
case 'lower tunnel': happensNext = 'You find a door, it is locked. You head back from where you came.';
break;
case 'hidden door': happensNext = 'You go through the door into a room. A small, very dark room, that smells of dust and sulfur...';
break;
default: happensNext = 'You stand there, gaping, not moving. Aiedra wonders, are you alive?';
break;
}
return happensNext;
}
sansTemple();

* challenge 1.24

function sansTemple(direction) {
var happensNext;
switch (direction) {
case 'right hallway':
case 'left hallway':
case 'forward hallway':
case 'lower tunnel': happensNext = 'You find a door, it is locked. You head back from where you came.';
break;
case 'hidden door': happensNext = 'You go through the door into a room. A small, very dark room, that smells of dust and sulfur...';
break;
default: happensNext = 'You stand there, gaping, not moving. Aiedra wonders, are you alive?';
break;
}
return happensNext;
}
sansTemple();

* challenge 1.25

function CaretakerMedallion(caretaker) {
switch (caretaker) {
case 'PixelPriest': this.bronzeBanner = 'Omne initium est a pixel';
case 'FontFriar': this.circumscribedSquare = 'Venit Comic Sans';
case 'StyleSensei': this.innerRing = 'Ars autem est in aeternum';
}
}

// Example uses of our CaretakerMedallion function
// Note the properties for each example

var medallion1 = new CaretakerMedallion('PixelPriest');
/*
CaretakerMedallion {
bronzeBanner: 'Omne initium est a pixel',
circumscribedSquare: 'Venit Comic Sans',
innerRing: 'Ars autem est in aeternum'
}
*/

var medallion2 = new CaretakerMedallion('StyleSensei');
/*
CaretakerMedallion {
innerRing: 'Ars autem est in aeternum'
}
*/

* notes 2.1

LOOP OPTIMIZATION

for loops can be optimized by removing memory access
for (var i=0; i< lilArray.length; i++)
for (var i=0, x=lilArray.length; i

* challenge 2.9

The bottom, just before the final tag.

* challenge 2.10

/* Mystical Page body html */

* challenge 2.11

JSBP

Level 2 Inverted Peninsula of Performance
Section 3 A blocking script in our path

Inhabitants of the Inverted Peninsula, Popn:

    * notes 2.12

    PERFORMANCE TIPS

    inheritance can help with memory efficiency
    moving methods to an object prototype makes them not created for every instance

    adding individual dom elements isn't always speedy
    each addition to the DOM causes document reflow
    use fragments to hold multiple elements that would have been used in a loop
    var fragment = document.createDocumentFragment();

    Declare variables as few times as possible
    use commas after the var keyword
    var x=1,
    y=3;

    Anticipate the use of variables in loops and declare before loop

    concatenation efficiency
    += is the fast way to do it
    except on arrays
    use join method
    textArray.join("\n");

    * challenge 2.13

    Prototypes should be used for shared properties and methods in order to increase memory efficiency.

    * challenge 2.14

    Use a Fragments to add conjunct elements, instead of touching the DOM over and over again.

    * challenge 2.15

    var list = document.getElementById('population'),
    inhabitants = ['Nipping Global Variable', 'Sneaky For-in', 'Bulging Blocking Script'],
    fragment = document.createDocumentFragment();

    for (var i = 0, x = inhabitants.length; i < x; i++) {
    var element = document.createElement('li');
    element.appendChild(document.createTextNode(inhabitants[i]));
    fragment.appendChild(element);
    }

    list.appendChild(fragment);

    * challenge 2.16

    Call the Array prototype's join() method on array.

    * challenge 2.17

    array.join(' ');

    * notes 2.18

    MEASURING PERFORMANCE

    console.time('string'); timer is started on this string
    console.timeEnd('string'); output string followed by milliseconds

    multiple timers can be run at same time on different strings

    averages of multiple times is needed to evaluate real time

    * challenge 2.19

    console.time is the opening statement to a timer method that will help us measure how long our code is taking to perform.

    * challenge 2.20

    true

    * challenge 2.21

    var array = ['Inverted Peninsula', ',', 'Inverted Peninsula', ', ', 'I', '—', 'P', '...', 'hmmm', '.'];
    var internalThoughts = '';
    console.time('join timer');
    internalThoughts = array.join(' ');
    console.timeEnd('join timer');
    console.log(internalThoughts);

    * challenge 2.22

    var array = ['Inverted Peninsula', ',',
    'Inverted Peninsula', ', ', 'I', '—',
    'P', '...', 'hmmm', '.'];
    var internalThoughts = '';

    console.time('Test');

    internalThoughts = array.join(' ');

    console.time('innerTest');
    console.log(internalThoughts);
    console.timeEnd('innerTest');

    console.timeEnd('Test');

    * challenge 2.23

    false

    * challenge 2.24

    Array.prototype.killTheInsolent = function(){};
    Array.prototype.countPopulace = function(){};
    Array.prototype.countUndeadPopulace = function(){};
    Array.prototype.insecticide = function(){};
    Array.prototype.shadowProvider = function(){};

    var invertedPeninsula = {
    inhabitants: ['Nipping Global Variable', 'Sneaky For-in', 'Bulging Blocking Script']
    };

    function populationGetter(){
    var population = invertedPeninsula.inhabitants;
    var list = "";
    console.time('string timer');

    for(var i = 0, ff = population.length; i < ff; i++){
    list += (population[i] + " ");
    }
    console.timeEnd('string timer');
    return list.trim();
    }

    populationGetter();

    * notes 2.25

    MEASURING PERFORMANCE 2

    to get actual measurements you need to numerical time data
    var rightNow = new Date();

    to get the time in milliseconds by using a +
    var rightNow = +new Date();

    a speed test class can be created the will run a function and average

    * challenge 2.6

    var IP = ['Nipping Global Variable', 'Sneaky Forin', 'Bulging Blocking Script'],
    GH = ['Switch Blocks', 'Pesky Gnat', 'Aiedra'],
    inhabitants = [IP,GH];

    function populationGetter(popn) {
    var list = '';
    for (var i = 0, x = popn.length; i < x; i++) {
    for (var j = 0; j < popn[i].length; j++) {
    list += (popn[i][j] + ', ');
    }
    }
    return list;
    }

    populationGetter(inhabitants);

    var concatTest = new SpeedTest(populationGetter, inhabitants, 100000);
    concatTest.startTest();

    * challenge 2.7

    var IP = ['Nipping Global Variable', 'Sneaky Forin', 'Bulging Blocking Script'],
    GH = ['Switch Blocks', 'Pesky Gnat', 'Aiedra'],
    inhabitants = [IP,GH];

    function populationGetterConcat(popn) {
    var list = '';
    for (var i = 0, x = popn.length; i < x; i++) {
    for (var j = 0; j < popn[i].length; j++) {
    list += (popn[i][j] + ', ');
    }
    }
    return list;
    }

    populationGetterConcat(inhabitants);

    function populationGetterJoin(popn) {
    var list = [];
    for (var i = 0, x = popn.length; i < x; i++) {
    list.push(popn[i].join(', '));
    }
    return list.join(', ');
    }

    populationGetterJoin(inhabitants);

    var concatTest = new SpeedTest(populationGetterConcat, inhabitants, 100000);
    concatTest.startTest();
    var joinTest = new SpeedTest(populationGetterJoin, inhabitants);
    joinTest.startTest();

    * notes 3.1

    CAREFUL COMPARISONS

    === will compare both type and content
    '4' == 4
    true == 1
    "\n " == 0 are true, but would be false with ===

    a === ensures comparison reliability

    to verify an objects class
    INSTANCEOF -> returns true if the object is of that class

    if (variable instanceof object)

    an object is an instance of all the prototypes that it inherits properties from

    * challenge 3.2

    ===

    * challenge 3.3

    Triple equals === is a safe default: it checks for matching content, as well as type.

    * challenge 3.4

    var strength = true;
    var fear = false;
    var pack = {
    foodPouch: ['carrot', 'mystery meat', 'apple', 42],
    addFood: function(foodItem) {
    this.foodPouch = this.foodPouch || [];
    this.foodPouch.push(foodItem);
    },
    gobbleFood: function(foodItem) {
    return(this.foodPouch.indexOf(foodItem) >= 0) ?
    this.foodPouch.splice(this.foodPouch.indexOf(foodItem), 1)[0] :
    alert('Your pack lacks ' + foodItem);
    },
    feedBird: function(birdFood) {
    for (var i = 0; i < this.foodPouch.length; i++) {
    if (this.foodPouch[i] === birdFood) {
    alert('Feed beggar bird ' + this.foodPouch[i]);
    }
    }
    }
    };

    pack.feedBird('42');

    * challenge 3.5

    true

    * challenge 3.6

    myNumberNommer instanceof DatatypeBird

    * challenge 3.7

    function Bird(){}
    function DatatypeBird(){}
    function SyntaxBird(){}
    DatatypeBird.prototype = Object.create(Bird.prototype);
    SyntaxBird.prototype = Object.create(Bird.prototype);

    var TryCatchTaster = function(){},
    SwitchSnagger = function(){},
    TernaryTracker = function(){};

    TryCatchTaster.prototype = Object.create(SyntaxBird.prototype);
    SwitchSnagger.prototype = Object.create(SyntaxBird.prototype);
    TernaryTracker.prototype = Object.create(SyntaxBird.prototype);

    var NumberNommer = function(){};
    NumberNommer.prototype = Object.create(DatatypeBird.prototype);

    var aTryCatchTaster = new TryCatchTaster();
    var aSwitchSnagger = new SwitchSnagger();
    var aTernaryTracker = new TernaryTracker();
    var aNumberNommer = new NumberNommer();

    var duneInhabitants = [aNumberNommer, aTryCatchTaster,
    aSwitchSnagger, aTernaryTracker];

    var count = 0;
    for(var i = 0; i < duneInhabitants.length; i++) {
    if (duneInhabitants[i] instanceof SyntaxBird) {
    count++;
    }
    }

    challenge 3.8

    true

    * challenge 3.9

    Despite their differences, instances of both NumberNommer and TryCatchTaster would share the Bird as a common ancestor.

    * notes 3.10

    EXCEPTION HANDLING

    an exception is a runtime error

    try block will throw errors to catch blocks
    try {
    alert(alarm);
    } catch (error) { error parameter is generated by try block
    alert("Uh oh: " + error);
    }

    you can use the error type to take proper action
    TypeError => wrong type of thing
    ReferenceError => thing is missing
    if (error instanceor ReferenceError) {

    js does not pinpoint all errors
    you need to use throw keyword to program your own exception

    throw
    if ((list instanceof Array) === false)) {
    throw new TypeError();
    }
    when a throw statement is reached, control passes to catch

    finally block
    executes wether errors were found or not

    try blocks can be nested

    * challenge 3.11

    A syntax error can be detected by the JavaScript parser before the program is ever executed, whereas a runtime error can be the result of trying to execute perfectly valid JavaScript.

    * challenge 3.12

    run-time

    * challenge 3.13

    function Bird(){}
    function DatatypeBird(){}
    function SyntaxBird(){}
    DatatypeBird.prototype = Object.create(Bird.prototype);
    SyntaxBird.prototype = Object.create(Bird.prototype);

    var TryCatchTaster = function(){} ;
    TryCatchTaster.prototype = Object.create(SyntaxBird.prototype);

    var NumberNommer = function(){};
    NumberNommer.prototype = Object.create(DatatypeBird.prototype);

    * challenge 3.14

    A JavaScript keyword used to identify and recover from errors is try.

    * challenge 3.15

    As soon as any sort of throw is reached, try passes control to catch.

    * challenge 3.16

    Whether errors occur or not, you can use a finally block to ensure some particular action is always taken, as long as it does not contain an error itself.

    * challenge 3.17

    // Pack of goods
    var pack = {
    foodPouch: ['carrot', 'mystery meat', 'apple', 42],
    addFood: function(foodItem) {
    this.foodPouch = this.foodPouch || [];
    this.foodPouch.push(foodItem);
    },
    feedBird: function(bird) {
    var food = bird.birdFood,
    foodIndex = this.foodPouch.indexOf(food);
    // If the exact food we want is not in the array,
    // check if the type of food is there.
    if (foodIndex === -1) {
    throw new ReferenceError('Bird food given is not available.');
    }
    bird.fed = true;
    }
    };

    // Parent Bird Class
    function Bird() {}

    // SyntaxBird Inherits From Parent Bird
    function SyntaxBird() {}
    SyntaxBird.prototype = Object.create(Bird.prototype);

    var LoopLover = function(birdFood) {
    this.birdFood = birdFood;
    this.fed = false;
    };
    LoopLover.prototype = Object.create(SyntaxBird.prototype);

    // DatatypeBird Inherits From Parent Bird
    function DatatypeBird() {}
    DatatypeBird.prototype = Object.create(Bird.prototype);

    var NumberNommer = function(birdFood){
    this.birdFood = birdFood;
    };
    NumberNommer.prototype = Object.create(DatatypeBird.prototype);

    // bird variables below inherit from above prototype chain
    var numba = new NumberNommer('42');
    var loopy = new LoopLover('loops');
    var tryCatcher = new LoopLover('la-de');

    // array of all the inhabitants
    var duneInhabitants = [numba, loopy, tryCatcher];

    // loop through duneInhabitants and if Bird call feedBird()
    for (var i = 0; i < duneInhabitants.length; i++) {
    try {
    pack.feedBird(duneInhabitants[i]);
    } catch (error) {
    console.log(duneInhabitants[i] +" was not fed.");
    }
    }

    * notes 3.18

    STUFF TO AVOID

    the 'with' statement
    creates a new local scope using a data container
    this allows to shorten longer property names
    the pitfalls are
    that variable creation inside these with blocks falls outside the object
    to avoid use variables for cacheing

    the 'eval' statement
    takes a string as a parameter and runs as a piece of code
    the pitfalls are
    strings that are improperly formatted can break
    if used for json - code insertion code happen
    try to use arrays to store data and not use eval to generate incrementing names
    json data should be parsed with JSON.parse()

    it is bad practice to leave off brackets on one liners
    makes for bad code reading
    is easy to break
    can create broken code that still runs

    * challenge 3.19

    redundancy, scope

    * challenge 3.20

    // Pack of goods
    var pack = {
    foodPouch: ['carrot', 'mystery meat', 'apple', 42],
    addFood: function(foodItem) {
    this.foodPouch = this.foodPouch || [];
    this.foodPouch.push(foodItem);
    },
    feedBird: function(birdFood) {
    var food = birdFood,
    foodIndex = this.foodPouch.indexOf(food);

    // If the exact food we want is not in the array,
    // check instead if the type of food is there.
    if (foodIndex === -1) {
    food = typeof food;
    for (var i = 0; i < this.foodPouch.length; i++) {
    if (typeof this.foodPouch[i] === food) {
    foodIndex = i;
    break;
    }
    }
    }

    // Check if we have the food in our pack.
    if (foodIndex >= 0) {
    console.log('You feed a beggar bird ' + food + '.');
    this.foodPouch.splice(foodIndex, 1);
    } else {
    console.log('Your pack lacks ' + food + ', Dhuun.');
    }
    },

    // Place in pack to keep your fire starting goods
    fireKit: {
    matchTin: {
    matches: 4,
    sparkPaper: 6
    }
    }
    };

    // Extra matches held outside of pack
    var matches = 3;
    function lightCampfire() {
    var tin = pack.fireKit.matchTin
    tin.matches--;
    tin.sparkPaper--;
    }

    * challenge 3.21

    var toolsForTheBug = [
    {bug: 'termite', tool: 'trebuchet'},
    {bug: 'slug', tool: 'sling'},
    {bug: 'caterpillar', tool: 'catapult'}
    ];

    function toolAssignment(number, tool) {
    toolsForTheBug[number].tool = tool;
    }

    toolAssignment(1, 'Sausage');

    * challenge 3.22

    var tools = JSON.parse(toolsForTheBug);

    * challenge 3.23

    var toolsForTheBug = [
    {bug: 'termite', tool: 'trebuchet'},
    {bug: 'slug', tool: 'sling'},
    {bug: 'caterpillar', tool: 'catapult'}
    ];

    function toolAssignment(number, tool) {
    toolsForTheBug[number].tool = tool;
    }

    toolAssignment(1, 'Sausage');

    * notes 3.24

    javascript uses binary floating point values to handle decimal operations
    used for performance, but reduces accuracy
    they are also not associative

    toFixed() method returns numbers rounded to indicated position
    var num = 0.1 + 0.2;
    num.toFixed(2) = '.30'
    toFixed returns a string

    parseFloat() turns strings with decimals into numbers
    used with toFixed it allows us to use values of exact length in other map operations

    parseInt() returns the integer part of a string number
    can behave bad when used with strings - NaN
    can cause unexpected value errors
    strings that start with 0 could be confused with octal
    parseInt can take a radix number to insure proper base is found
    parseInt('021', 10); should always be used

    checking for numbers can be difficult
    Not a Number NaN is considered a number itself
    isNaN only returns true for NaN
    we need to use both isNaN and typeof to guarantee
    if (typeof data === "number" && !isNaN(data))
    checking the value is a number and not the NaN value

    form data should always be parsed before being checked for type

    * challenge 3.25

    var birdFeeder = {
    totalFeed: 4,
    getFeed: function(feedRequested) {
    var returnedFeed = 0;
    if (this.totalFeed >= feedRequested) {
    returnedFeed = feedRequested;
    this.totalFeed -= feedRequested;
    } else {
    returnedFeed = this.totalFeed;
    this.totalFeed = 0;
    }

    return parseFloat(returnedFeed.toFixed(1));
    },
    fillFeed: function(additionalFeed) {
    this.totalFeed += additionalFeed;
    }
    };

    * challenge 3.26

    parseInt(lambString, 10);

    * challenge 3.27

    parseFloat(lambString, 2);

    * challenge 3.28

    parseInt() will accept any radix value between 2 and 36 upon which to base the numerical string it has received.

    If you cannot be assured of browser version, user's input, or data type, use both typeof and the function isNaN() concurrently as a best practice to ensure you are receiving numbers only.

    * notes 4.1

    NAMESPACING BASICS

    conflicting code w/i multiple js files can cause conflicts

    javascript namespaces are simulated

    by using an object as a data container, we add a laywer of protection around data
    this namespace object is usually capitalized
    variables will become properties

    ideally all incorporated js files should use a NAMESPACE

    namespaces are agnostic of each other
    which is useful for data protection

    nested namespacing is frequent in a module pattern

    * challenge 4.2

    An object that groups and protects related data and methods in JavaScript files is called a namespace.

    * challenge 4.3

    1) overwrite, 2) globally, 3) run-time

    * challenge 4.4

    var CAVESYSTEM = {
    stalactites: 4235,
    stalagmites: 3924,
    bats: 345,
    treasureChests: 3,
    openChest: function() {
    this.treasureChests--;
    alert('DA DADADA DAAAAAAA!');
    }
    };

    * challenge 4.5

    Caves of Clarity

    Open the Secret Treasure!

    * challenge 4.6

    "A namespace ensures complete privacy of data."
    Is this statement True or False? FALSE

    * challenge 4.7

    var CAVESOFCLARITY = {
    stalactites: 4235,
    stalagmites: 3924,
    bats: 345,
    SECRET: {
    treasureChests: 3,
    openChest: function() {
    this.treasureChests--;
    alert('DA DADADA DAAAAAAA!');
    }
    }
    };

    * challenge 4.8

    Caves of Clarity

    Open the Secret Treasure!

    * challenge 4.9

    If built well, namespaces remain AGNOSTIC of other namespaces.

    If another file, with another namespace, is needed for the Caves' HTML file, the two files should not know of each other. This can aid in your data protection.

    * notes 4.10

    ANONYMOUS CLOSURES

    public methods and values often trigger private methods and values
    'closure' allows us to privatize properties

    all properties are wrapped in an anonymous immediately invoked function expression (IIFE)
    local values and methods are made executable
    ending parentheses indicate immediate execution
    it is a good habit to move all private values to top
    to make properties public we create and return an object with these

    var ARMORY = (function(){
    var weaponList = ['sword','axe'];
    var removeWeapon = function(…){};
    return {
    askForWeapon: function(…){}
    }
    })();

    this will return the object as the namespace

    * challenge 4.11

    What feature of JavaScript is used to cause some properties to be private, bound only to a surrounding function's local scope, and some properties to be public, accessible by all holders of the namespace? closure

    * challenge 4.12

    Private, created, function expression, Public, object, returned, namespace, private, closure, module

    * challenge 4.13

    var CAVESOFCLARITY = function() {
    var treasureChests = 3;
    return {
    stalactites: 4235,
    stalagmites: 3924,
    bats: 345,
    SECRET: {
    openChest: function() {
    treasureChests--;
    alert('DA DADADA DAAAAAAA!');
    }
    }
    };
    }();

    * challenge 4.14

    treaseChests––;

    * challenge 4.15

    var CAVESOFCLARITY = function() {
    var treasureChests = 3,
    bats = 345;
    return {
    stalactites: 4235,
    stalagmites: 3924,
    SECRET: {
    openChest: function() {
    treasureChests--;
    alert('DA DADADA DAAAAAAA!');
    }
    }
    };
    }();

    * challenge 4.16

    Since it's never accessed through the public methods, the private bats datum holds no functional purpose.

    * challenge 4.17

    var CAVESOFCLARITY = function() {
    var treasureChests = 3;
    var bats = 345;
    return {
    stalactites: 4235,
    stalagmites: 3924,
    SECRET: {
    openChest: function() {
    treasureChests--;
    alert('DA DADADA DAAAAAAA!');
    }
    },
    getBats: function() {
    return(bats);
    }
    };
    }();

    * challenge 4.18

    The parentheses that immediately invoke the function.

    * notes 4.19

    GLOBAL IMPORTS

    global variables used inside a namespace makes searching the entire scope change to find global
    developers will have a hard time tracing because of unclear scope
    global variables can get accidentally change

    for clearer, faster globals use imports
    add a parameter to the wrapper immediately invoked function
    change globals in namespace to new parameter
    pass in globals into IIFE using calling expressions

    variable is closed as a local value
    global stays protected

    * challenge 4.20

    If a module references globally-scoped variables, it's a best practice to bring them into the scope of anonymous closure through the use of a specific technique.

    What is the name for this? Global Import

    * challenge 4.21

    var LEXICALLAKE = (function(answer) {

    var depth = 400;
    var fish = 1200;
    var unknownSleepers = 3;

    return {
    getFish: function() { return fish; },
    getDepth: function() { return depth; },
    getSleepers: function() {return unknownSleepers; },
    awakenSleeper: function() {
    alert('Far below, in the deep, something awakens. Row faster.');
    },
    summonBoat: function() {
    if (answer === 'agnostic') {
    alert('The boat fades into view.');
    }
    else {
    alert('...the lake is silent.');
    }
    }
    };
    })(explorerAnswer);

    * challenge 4.22

    Your import ensures clarity of scope within a module.
    By using a parameter, you protect the global data that might have been overwritten.
    All imported data becomes locallu scoped to the anonymous function, to be used in closure.
    Thus, when compared with searching the entire scope chain, imports are both clearer and faster.

    * challenge 4.23

    var LEXICALLAKE = (function(answer, foundShore) {
    var depth = 400;
    var fish = 1200;
    var unknownSleepers = 3;
    return {
    getFish: function() { return fish; },
    getDepth: function() { return depth; },
    getSleepers: function() { return unknownSleepers; },
    awakenSleeper: function() {
    alert('Far below, in the deep, something awakens. Row faster.');
    },
    summonBoat: function() {
    if (answer === 'agnostic') {
    alert('The boat fades into view.');
    }
    else {
    alert('...the lake is silent.');
    }
    },
    stopSleeper: function() {
    if (foundShore) {
    alert('That which has awoken shall now return to slumber.');
    }
    else {
    alert('A Sleeper cometh. Abandon hope.');
    }
    }
    };
    })(explorerAnswer, madeItAcross);

    * notes 4.24

    AUGENTATION

    when updating or adding additions to a module it is often better to seperate into files

    augmentation is using a separate file to add functionality to a module
    in a separate file we build a namespace with same namespace
    we import the old namespace via last lesson
    we get a new object with added functionality

    new functions do not get to see closed data in original namespace

    group file contents around related data

    * challenge 4.25

    What is the term for adding or changing properties in a module after the module has already been built? Augmentation

    * challenge 4.26

    CAVESOFCLARITY = (function(caves) {
    var sandScript = '';
    caves.setSandScript = function(message) {
    sandScript = message;
    };
    return caves;
    })(CAVESOFCLARITY);

    * challenge 4.27

    In simple augmentation, the module file and the augmentation file do not share their private state.
    Augmented module properties may only access the private data from their file's closure.
    Private data from the original closure will not be lost, and will be accessible to all original properties that referenced it.

    AttachmentSize
    codeschool notes.txt32.34 KB

    Komentáře

    Poslat nový komentář

    • Povolené HTML značky: <em> <strong>
    • Řádky a odstavce se zalomí automaticky.

    Více informací o možnostech formátování

    Image CAPTCHA
    Enter the characters shown in the image.