Coding Practice - JavaScript (Codeacademy)

Here are my rough notes from Codeacademy's JavaScript tutorial. This tutorial only covered "JavaScript in a vacuum" and not JavaScript's usual purpose of interacting with HTML, so I want to return to this language once I've completed Codeacademy's offerings.


FOREWORD

This will probably be a two-part set of notes, first looking at JS in a vacuum, and then looking at JS's interactions with other languages (ex. HTML)


BASICS

JavaScript is generally used for making interactive websites. It runs in the user's browser (unlike PHP), meaning it can take input and then perform actions with that input.

If you put an evaluable expression alone in a page (ie, just write 2+4, or "myString" without assigning them to a variable) the result will be printed to output.

"String".length

A + B - C * D / E % F

a < b > c <= d >= e

Javascript supports both type-converting comparison (==, !=) and strict comparison (===, !==). For example, false == 0 and false === false both evaluate true, but false === 0 evaluates to false.

true false

//Comment

Semi-colons designate the end of a line, but JS can still run without them. It's probably good practice to use semi-colons whenever possible.

confirm(String) displays a popup with String text, and buttons OK and Cancel. Pressing OK returns true, pressing Cancel returns false.

prompt(String) displays a popup with String text, and a field for the user to input some text. Returns a string containing the user's input.

console.log(expression) will evaluate expression and print it to the console. This is useful for printing text inside of functions which would not otherwise return that text.


STRINGS

"String".length

"String".substring(leftIndex, rightIndex) returns the string from leftIndex to rightIndex-1.


VARIABLES

JavaScript variables are implicitly-typed. We declare them with "var", like 'var myName = "Eric";'


FUNCTIONS

Javascript functions are stored inside of variables The syntax is: var myFunction = function(myParameter1, myParameter2... ){myCode};

Javascript functions can also be created "freestanding" like function myFunction(myParam){}; The difference between this version and the one above is that this version is defined at parse-time (allowing declare-after-use but not lambda) whereas the above is defined at runtime (allowing lambda but not allowing declare-after-use).

Functions are then invoked with the name of the variable: myFunction(myArguments);

Functions can return a value with the "return" keyword, but they may also return nothing. Remember JS is implicitly typed, so we have a lot of freedom.

Variables declared outside of functions are "global", variables decalred inside functions are "local"

ARRAYS

Arrays are a datatype that can store a sequence of data. In Javascript, arrays are "heterogeneous", meaning multiple types of data can be stored in a single array.

JavaScript allows multidimensional arrays (ie, arrays inside arrays) and it allows those multidimensional arrays to be jagged (ie, the arrays stored in a particular dimension can have different lengths)


IF/ELSE/SWITCH

if-statements work exactly like C. if(expression){action}. "else if()" and "else" are also available and work like you would expect.

switch statements have the following syntax:
switch(myExpression){
    case 'myValue1':
        myResponse1;
        break;
    case 'myValue2':
        myResponse2;
        break;
    ...
    default: myDefaultResponse;
}

If a switch statement case doesn't end with break, it will "fall through" and execute the response of the next case as well, which can chain until it hits a break or executes the default.


FOR LOOPS

Syntax is: for (var myIndex = startingValue; booleanExpression; modifyIndexExpression){myCode}

JS does not have any cool Python-style interaction between for-loops and arrays. Instead have to just count from index=0 to index===array.length and then use array[index].


WHILE LOOPS

While loops work exactly like you would expect in other languages:

while(condition){
    myCode
}


Do-while loops will always execute the code after "do" at least once, and then repeat the loop if the while condition is true.

do{
    myCode
} while (loopCondition);


LOGICAL OPERATORS

and == &&

or == ||

not == !

Note that the single characters &, |, ^ and ~ are used for bitwise operations (ie, they operate on numbers, not booleans).


OBJECTS

Objects can be created using literal notation, as follows:

var myObject = {
    key1: value1,
    key2: value2,
    key3: value3
};

Objects can also be created using a constructor:

var myObject = new Object();
myObject["key1"] = value; (or) myObject.key1 = value;

Note that when we use dot (.) notation to access a key, the thing after the dot has to be a string. Bracket ([]) notation allows us to use any expression to determine the key. We could call a function which returns the name of the key.

--

Once we've added keys to an object, we can fill some of those keys wth the object's methods, like so:

var myObj = new Object();
myObj.myVar = 0;
myObj.setMyVar = function (newValue){
    myObj.myVar = newValue;
};

And then call the method like:

myObj.setMyVar(123);

--

"this" can be used when creating functions so that those functions can be used as methods by several different objects. For example:

var setMyKey = function(newValue){
    this.myKey = newValue;
};

obj1.setMyKey(5);
someOtherObj.setMyKey(9);

--

Creating objects with the default constructor gives them no properties (and thus no methods)... which is annoying when we want several instances of a single kind of object. Instead, we may want to define custom constructors.

The syntax is:

function myConstructor(params1){
    this.key1 = value1;
    this.key2 = value2;
    this.key3 = function(params2){
        methodCode
    };
}

var myInstance = new myConstructor(arguments);


BUILT-IN METHODS AND FUNCTIONS FOR OBJECTS

JavaScript is implicitly typed, but we can still check the type of a variable using the keyord "typeof", like: console.log(typeof 5) would print "number." Typeof does not distinguish between different types objects however (ie, it'll only return "object" even if you use a custom constructor)

To help us distinguish between different objects, JavaScript gives every object the method "hasOwnProperty(name)." Calling myObj.hasOwnProperty("myName") returns true or false depending whether or not myObj has a property named myName.

--

"for(var someName in someObj){someCode};" allows us to loop through every property in an object.


CLASSES

When people talk about classes in JavaScript, they're basically talking about custom constructors. If you create a custom constructor, then you've defined a class.

When we create a custom constructor, JavaScript remembers a "prototype" representing the class and containing all the things which every member of the class should have.

Prototypes matter because we can modify them to add new keys to all members of a class. Remember that we only defined a constructor, and the constructor is only called when an instance is initially created... so modifyng the constructor (our "class") at runtime wouldn't actually update any preexisting instances. We have to work through the prototype.

The syntax is:
someCustomConstructorName.prototype.keyName = function(){ code };

--

Whenever we create an object, that object "inherits" methods and properties from the class defined by the constructor.

When we create a class, we can also inherit methods and properties from other classes. We do this by setting the prototype of our class to an instance of the parent. Interestingly, this does NOT wipe out anything in the child's prototype which was not in the parent. So it's not a normal assignment... which I guess is fine since operators can be overridden for classes in most languages. I guess they just overrote the = operator for the Prototype class.
The syntax is:

function parent(){}
function child(){}
child.prototype = new parent(); //Note: arguments do not need to be provided for the parent's constructor.

If JavaScript cannot find a called method/property, it will look "up" the chain of inheritence until it either finds a definition or reaches the end. This means children can override a parent's definitions, and that "younger" parents will override older ones.


PUBLIC AND PRIVATE VARIABLES

By default object properties are "public," meaning they are accesible from outside of the class (ie var myVar = myInstance.someProp)

We can also create "private" properties by declaring them inside the constructor like normal variables, instead of using "this.var" syntax.

The syntax is:

function myClass(params){
    this.firstProp = someValue1; //public
    var secondProp = someValue2; //private
};

If we want to access private variables from outside the class, we need to create public "interface methods" which are inside the class and can then access those internal variables. Note that JavaScript does "copy-by-value", so returning the internal variable will not allow the base variable to be modified from outside. (ie, we need get and set, not just get)

Of course, since methods generally ARE variables, we can define private methods which will not be accessible from outside the class either.