Strings:
"hello world"
Numbers:
4
null:
null
Booleans:
true; false
String ops:
+
concatenates strings.
+
with a string converts a number to string
var firstName = "Jacob";
var lastName = "Lyles";
var iceCream = 5;
var fullName = firstName + " " + lastName;
var message = fullName + " ate " + iceCream + " ice creams today";
Functions:
var fun = function(foo){
console.log("hello", foo);
}
fun("NTU"); // logs "hello NTU"
function fun2(foo){
console.log("hello", foo);
}
fun2("NTU"); // logs "hello NTU"
undefined:
var a = undefined;
var b;
a === b => true
console.log(b); // logs undefined
function printer(foo) {
console.log(foo);
}
printer(); // logs undefined
if(!undefined){ console.log("hello"); } // logs "hello"
Arrays:
var arr = [1,"a", 3, null];
arr[0]; => 1
arr[3]; => null
arr[4]; => undefined
arr[-1]; => undefined
arr.length; => 4
arr.push("hello");
arr.length; => 5
console.log(arr); // prints [1, "a", 3, null, "hello"]
Array Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Objects:
var obj = {"a": 1, "b": []};
obj["a"] => 1
obj.b => []
obj["c"] => undefined
obj.hasOwnProperty("a") => true
"a" in obj => true
Iterate over object properties with for
loops
for (var key in obj){
console.log(key, obj[key]);
}
typeof:
typeof
tells type of a variable, but results can be unexpected:
typeof(2) => "number"
typeof(true) => "boolean"
typeof(undefined) => "undefined"
typeof({}) => "object"
typeof(null) => "object"
typeof([]) => "object"
Boolean warning
- all these things are "falsy"
- have to check for them explicitly
null
0
""
undefined
Dates
var now = new Date();
now => Fri May 09 2014 05:50:40 GMT-0700 (PDT)
var yesterday = new Date();
yesterday.setDate(now.getDate() - 1)
yesterday => Thu May 08 2014 05:51:48 GMT-0700 (PDT)
Serialization with JSON
JSON: a string format for storing JS objects
var json = '{ "name": "Nick" }';
try {
var nick = JSON.parse(json);
nick.name; // "Nick"
} catch (e) {
console.error(e);
}
var dog = { name: "Winston", type: "Bulldog", };
JSON.stringify(dog); // '{ "name": "Winson", "type": "Bulldog" }'
"First class functions" -> use functions like any other variable
var doBefore = function (doAfter){
console.log("outer function");
doAfter();
}
doBefore(function(){
console.log("inner function");
}); // logs "outer function" \n "inner function"
passing the function to do next as a variable is the "callback" pattern
var arr = [];
var fun = function(){ console.log("hello!"); }
arr.push(fun);
arr.length => 1
arr[0](); // logs "hello!"
functions create new scope
var fun = function(foo){
var secondFun = function(innerFoo){
// variable 'foo' is available from outer scope!
console.log(foo, innerFoo);
}
// using "innerFoo" here would result in an error
secondFun("second");
}
fun("first"); // logs "first second"
Object oriented JS
- no "classes" in JS
- object instances are built with
constructor
functions
- inheritance happens with
prototypes
- Calling a function with
new
makes it a constructor function
- Inside a constructor, "this" is a new object
- The new object is returned from the constructor
function Character(firstName, lastName, hp){
this.name = firstName + " " + lastName;
this.hp = hp;
}
var char1 = new Character("Zhenghao", "Chen", 100);
var char2 = new Character("Jacob", "Lyles", 200);
char1.name => "Zhenghao Chen";
char1.hp => 100
char2.name => "Jacob Lyles";
char2.hp => 200
Methods
- methods are a property of an object that is a function
- inside a method,
this
refers to the object that "owns" the function
function Character(firstName, lastName, hp) {
this.name = firstName + " " + lastName;
this.hp = hp;
}
var char1 = new Character("Jacob", "Lyles", 200);
char1.takeDamage = function(damage){
this.hp - damage;
console.log(this.hp + " is left");
}
char1.takeDamage(50); // logs "150 is left"
Inheritance
- objects inherit properties from the constructor's prototype
- the prototype acts as a fallback if an undefined property is called on the instance
function Character(firstName, lastName, hp) {
this.name = firstName + " " + lastName;
this.hp = hp;
}
Character.prototype.takeDamage = function(damage) {
this.hp -= damage;
console.log(this.hp + " is left");
}
var char1 = new Character("Jacob", "Lyles", 200);
char1.hasOwnProperty("takeDamage") => false
char1.takeDamage(50); // logs "150 is left"
Inheritance
Object.create
makes a new object with the given prototype without calling the constructor (not available in older browsers)
function FrostKnight(firstName, lastName, hp) {
this.name = firstName + " " + lastName;
this.hp = hp;
this.type = "ice";
}
FrostKnight.prototype = Object.create(Character.prototype);
FrostKnight.prototype.frostArmor = function(){
this.hp += 100;
console.log(this.hp + " is left");
};
var iceChar = new FrostKnight("Jacob", "Lyles", 200);
iceChar.takeDamage(50); // logs "150 is left"
iceChar.frostArmor(); // logs "250 is left"
Inheritance
The prototype of an instance can be checked with Object.getPrototypeOf
function FrostKnight(firstName, lastName, hp) {
...
}
FrostKnight.prototype = Object.create(Character.prototype);
var iceChar = new FrostKnight("Jacob", "Lyles", 200);
var iceProto = Object.getPrototypeOf(iceChar)
iceProto === FrostKnight.prototype => true
iceChar.hasOwnProperty("takeDamage") => false
iceProto.hasOwnProperty("takeDamage") => false
Object.getPrototypeOf(iceProto).hasOwnProperty("takeDamage") => true
"takeDamage" in iceChar => true
Changing this
bind
sets the value of this
in a function
- this code erroneously logs "NaN is left"
FrostKnight.prototype.delayedMeltDamage = function(damage){
setTimeout(this.takeDamage, 5000, damage);
};
var iceChar = new FrostKnight("jacob", "lyles", 200);
iceChar.delayedMeltDamage(50);
But this will work:
FrostKnight.prototype.delayedMeltDamage = function(damage){
setTimeout(this.takeDamage.bind(this), 5000, damage);
};
var iceChar = new FrostKnight("jacob", "lyles", 200);
iceChar.delayedMeltDamage(50);
The options object pattern
function Character(firstName, lastName, hp, type, boss, level, world, bio, background){
...
}
function Character(opts){
...
}
The defaults pattern
In JS, foo || "default"
evals to "default"
if foo
is false, undefined, null
or another "falsy" object
function Character(opts){
this.name = opts.name || "Jack NoName";
this.hp = opts.hp || 200;
}
The module pattern
When you load a JS file, variables get added to the global name space. Two files that define variables of the same name will cause a collision
<script src="character.js"></script>
<script src="enemy.js"></script>
// in character.js
var DEFAULT_HP = 500;
// in enemy.js
var DEFAULT_HP = 1000;
// value from enemy.js overwrites value in character.js
The module pattern
- Since functions create scope, wrap files in a function and only add what is needed to the global namespace
- In the browser, the global namespace is called
window
. All values available by default are properties of window
(function(global){
var DEFAULT_HP = 1000;
var Enemy = function (){
...
}
window.Enemy = Enemy;
})(window);
window.DEFAULT_HP => undefined
window.Enemy => function