Last active
August 29, 2015 14:10
-
-
Save vlandham/35cea116592bec45092e to your computer and use it in GitHub Desktop.
Gist from mistakes.io
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------- | |
// types | |
// -------- | |
// falsy values | |
function is_false(value) { return !(value); }; | |
is_false(false); | |
is_false(undefined); | |
is_false(undefined); | |
is_false(NaN); | |
is_false(""); | |
is_false(0); | |
// types | |
function a_function() {}; | |
typeof false; | |
typeof 0; | |
typeof "a"; | |
typeof undefined; | |
typeof a_function; | |
typeof {}; | |
// more types | |
typeof NaN // NaN is a number | |
// type gotchas | |
typeof []; // returns 'object' | |
typeof null; // returns 'object' | |
NaN == NaN; // NaN is not equal to any number. including self... | |
0 == false; // makes sense. both are falsy | |
0 == undefined; // ??? | |
//ternary | |
//(true == true) ? "YES" : "NO"; | |
//(false == true) ? "YES" : "NO"; | |
//var value = true == true ? "YES" : "NO"; | |
//value | |
// -------- | |
// objects | |
// -------- | |
var obj = {}; | |
// names | |
obj.name = "hello"; | |
obj["name"] = "goodbye"; | |
obj.name; | |
// default value | |
var value = obj.not_here || "YES"; | |
value; | |
// but watch out! | |
obj.falsy = 0; | |
value = obj.falsy || "YES"; | |
value; | |
// undefined retrieval | |
// obj.not_here.dont; // throws type error | |
obj.not_here && obj.not_here.dont; // returns undefined | |
// objects passed by reference | |
obj = {}; | |
obj.name = "SAM"; | |
another_obj = obj; | |
another_obj.name = "CARL"; | |
obj.name; | |
// object prototypes | |
// create | |
if (typeof Object.create !== 'function') { | |
Object.create = function(o) { | |
var F = function() {}; | |
F.prototype = o; | |
return new F(); | |
}; | |
} | |
obj; | |
// assigning prototype | |
var another_obj = Object.create(obj); | |
another_obj; | |
another_obj.name; // prototype used to retrieve property | |
another_obj.name = "KID"; | |
obj.name; // object's prototype is not touched on updates | |
another_obj; | |
// dynamic linkage | |
another_obj.age; | |
obj.age = 19; | |
another_obj.age; // on the fly - after prototype is assigned. | |
// object reflection | |
// use typeof to figure out what an object has | |
typeof another_obj.name; | |
typeof another_obj.age; // all the way up the chain | |
typeof obj.not_there; | |
// undesired properties | |
typeof obj.constructor; | |
// use hasOwnProperty | |
obj.hasOwnProperty("constructor"); | |
another_obj.hasOwnProperty("age"); // doesn't look at chain | |
// for in will include chained properties | |
var n; | |
for (n in another_obj) { | |
n; | |
} | |
// delete property | |
another_obj.name; | |
delete another_obj.name; | |
another_obj.name; // getting it from up chain | |
delete another_obj.age; // doesn't go up chain | |
another_obj.age; // getting it from up chain | |
obj.age; | |
// -------- | |
// functions | |
// -------- | |
// functions are objects and thus can be assigned to vars | |
var func = function(name) {return name + " FUNCTION";}; | |
// this is still an anonymous function - as it has no name | |
func('one'); | |
// and can have properties... | |
func.type = "a function"; | |
func.type; | |
func.name; // why a blank string ??? | |
// has parameters: 'arguments' and 'this' | |
var argsFunc = function() {return arguments;}; | |
argsFunc(); | |
argsFunc("one"); | |
argsFunc("one", "two"); | |
// arguments is 'array-like' object | |
// --- | |
// function invocation patterns | |
// --- | |
// 4 types: method, function, constructor, apply | |
// determine what 'this' is set to | |
// * method invocation pattern | |
// when function is property of object, this is bound to that object | |
var obj = { | |
name: "OBJECT", | |
func: function() { return this;} // func is a method | |
}; | |
obj.func(); | |
// * function invocation pattern | |
// when not a property of an object then function is a function | |
// 'this' is the global object (mistake) | |
// problem: if a method has an inner function, then 'this' is bound to | |
// global object in inner function, instead of method's object | |
name = "GLOBAL"; | |
var bad_obj = { | |
name: "OBJECT", | |
func: function() { | |
helper = function() { return this.name + " NAME";}; | |
return helper(); | |
} | |
}; | |
bad_obj.name; | |
bad_obj.func(); | |
// * constructor invocation pattern | |
// using 'new' can assign prototype. | |
// changes 'this' to linked prototype | |
var Parent = function() { | |
this.name = "PARENT"; | |
}; // convention to use capital name for 'constructors' | |
Parent.prototype.func = function () { | |
return this.name; | |
}; | |
var myChild = new Parent(); // 'this' is returned | |
myChild.func(); | |
// * Apply Invocation Pattern | |
// functions can have methods - such as 'apply' | |
var other = {name:"OTHER"}; | |
// first argument is what 'this' should be | |
Parent.prototype.func.apply(other); | |
// exceptions | |
try { | |
throw {name:'error', message:"ERROR"}; | |
} catch(e) { // <- only one catch block | |
e; | |
} | |
// augmentation | |
// (monkey patching) | |
// add to prototype to make new function availilble. | |
// works on many different types | |
// - functions | |
Function.prototype.method = function(name, func) { | |
this.prototype[name] = func; | |
return this; | |
}; | |
// adding a method to numbers | |
Number.method('integer', function() { | |
return Math[this < 0 ? 'ceil' : 'floor'](this); | |
}); | |
(-10 / 3).integer(); | |
7.9.integer(); | |
// recursion | |
var hanoi = function hanoi(disc, src, aux, dst) { | |
if (disc > 0) { | |
hanoi(disc - 1, src, dst, aux); | |
var s = "Move disc " + disc + " from " + src + " to " + dst; | |
s; | |
hanoi(disc - 1, aux, src, dst); | |
} | |
}; | |
hanoi(3, 'Src', 'Aux', 'Dst'); | |
// scope | |
// has function scope - but not block scope | |
// variable defined anywhere in that function are accessible | |
// within rest of the function... | |
var ddd = function() { | |
var a = 3, b = 5; | |
var inner = function() { | |
var b = 6, c = 11; | |
(a + b); | |
}; | |
inner(); | |
a; | |
}; | |
ddd(); | |
//futured; | |
//futured = "eee"; // this supposed to work ??? | |
// module | |
// function that defines private variables & functions that only | |
// privileged functions have access to - through closure | |
// function returns privileged functions to make them accessible | |
// can be used to protect variables | |
var serial_maker = function() { | |
var prefix = ''; | |
var seq = 0; | |
return { | |
set_prefix: function(p) { | |
prefix = String(p); | |
return prefix; | |
}, | |
set_seq: function(s) { | |
seq = s; | |
return seq; | |
}, | |
gensym: function() { | |
var result = prefix + seq; | |
seq += 1; | |
return result; | |
}, | |
}; | |
} | |
// cant access prefix or seq except by | |
// defined methods. | |
var seqer = serial_maker(); | |
seqer.set_prefix('Q'); | |
seqer.set_seq(1000); | |
seqer.gensym(); | |
seqer.gensym(); | |
seqer.set_seq('A'); | |
seqer.gensym(); | |
seqer.gensym(); | |
seqer.gensym(); | |
// 'arguments' is array-like. not an array | |
// can change by using slice. | |
var args_slice = function() { | |
var slice = Array.prototype.slice; | |
var args = slice.apply(arguments); | |
return args; | |
} | |
args_slice(); | |
args_slice('hello'); | |
args_slice('hello', 'again'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment