- Comment
- Single line comment: //
- Multiline comment /* */
- Combining multiple initialization is better as JS Engine would be faster at executing a single statement
var first = 10,
second = 15,
third = "third";console.dir()to print something as is, without quotes and such.- For comparison conditions that involve stuff like array length, initialize another variable with the length property instead of computing like on every single iteration
for (var i=0; i < arr.length; i++);is slower than
for (var i=0, l=arr.length; i < l; i++);'0'isfalse(unlike PHP)'false'istrue[]istrue(unlike PHP){ }istrue
number(integers as well as floating point),string,boolean,Object(array,object,Date,RegExp,null),function.nullandundefinedtypes can't contain any values.
typeofto get the type of anything.- No
isDate,isStringfunctions (there isArray.isArray()though)typeofbut this fails as it returnsObjectfor all objects including user-defined types andnull.instanceofThis fails in case of iframes.- Duck typing e.g. check
typeofof a property/method of the object at hand and ensure it is not"undefined". This could also fail where we are checking for a property/method that exists across multiple types or if we send in a user-defined object with just that property/method. return Object.prototype.toString.call(myString) === '[object String]';but this would also fail for use-defined objects
function type(obj){ var text = obj.constructor.toString() return text.match(/function (.*)(/)[1] }
This is going to be slow (which we can improve by using ```indexOf()``` and ```substr()```), also open to shadowing:
```javascript
Array.toString = function(){ return "function NotArray(){ }" }
type([1,2,3]) // "NotArray"
and would not perform well with user types:
var f = function Animal(){ "something" }
var g = function Animal(){ "something entirely different" }
type(new f) // "Animal"
type(new g) // "Animal"- MDN uses fourth option as
polyfillrecommendations - Type conversion
!!to convert anything to a boolean // or the explicitBoolean(x)works too- Convert number to string:
6 + ""; // "6", internally gets resolved to(6).toString() + ""String(6)(6).toString(), fastest per http://jsperf.com/number-to-string/2toString()behavior:[10,20] // "10,20"true // "true"false // "false"{ } // [Object object]- rest are as expected.
- Converting strings to Numbers:
- Parse number from string:
parseInt("12a11", 10); // 12parseInt("s123", 10); // NaNparseInt()can also work on floats and return the floor value.
- Parse float from a string:
parseFloat("3.14e1", 10); // 3.14
- Parse a number(whether it is float or integer)
Number("123"); // 123Number("3.14519"); // 3.14519Number(""); // 0Number(" "); //0Number("yellow"); // NaN+ "61.2"; // or - "61.5" both will return 61.5"6" - 0; // or "6" / 1; or "6" * 1;
- Parse number from string:
- Binary Addition operator unique behavior
4 + 5 + "7" + 6 + 5 // "9765"- This behavior is only unique to addition/concatenation operator. For deduction, multiplication or division string will be converted to a number
lengthindexOf(key,[ offset[)lastIndexOf(key[, fromIndex])search(regex)- use indexOf as that is faster, unless we really need to use regex
charAt(index)startsWith(searchString[, position])endsWith(searchString[, lastPosition])slice(beginSlice[, endSlice])- returns new string
split([separator[, limit]])- returns array, missing separator: whole string as one array element, empty string separator: character array
substring(indexA[, indexB])- returns sting, order of parameters is not relevant, same result is return regardless. non-int or negative are treated as 0, greater than str.length is treated as
str.lengthimplicitly
- returns sting, order of parameters is not relevant, same result is return regardless. non-int or negative are treated as 0, greater than str.length is treated as
substr(start[, length])- returns sting, better version of substring() with proper support for negative indexes, parameter order does matter, both indexes are inclusive.
toLowerCase()- returns new string
toUpperCase()- returns new string
trim()- returns a new string with whitespace chopped of. trimLeft() and trimRight() exist but are not part of standard, may be use polyfills to use those if really needed.
replace(str|regex, replacementStr|replacementExpr);- returns new string. regex e.g. /matchThis/gi (gi = global and case insensitive), replacement could be a single string or use replacement patterns with
$nwhere n is the match found
- returns new string. regex e.g. /matchThis/gi (gi = global and case insensitive), replacement could be a single string or use replacement patterns with
- Most function take a callback of the format
function(value, index, array) {
}lengthconcat(value1[, value2[, ...[, valueN]]])- returns a new array
filter(callback[, thisArg])- returns a new array
forEach(callback[, thisArg])indexOf(searchElement[, fromIndex = 0])join([separator = ','])- returns string
lastIndexOf(searchElement[, fromIndex = arr.length - 1])map(callback[, thisArg])- returns a new array after applying callback
pop()push(element1, ..., elementN)- returns new length
reduce(callback[, initialValue])- callback takes:
(function(previousValue, currentValue, index, array), tries to merge all values and return a single value
- callback takes:
reverse()- reverse the order, in place
shift()- removes and returns first element
unshift([element1[, ...[, elementN]]])- adds elements at the start, returns new length
slice([begin[, end]])- returns sliced array, end not inclusive
every(callback[, thisArg)- tests if every element passes a test
some(callback[, thisArg])- tests if some elements pass a test or not
sort([compareFunction])- by default sorts by unicode values
splice(start, deleteCount[, item1[, item2[, ...]]])- delete and/or add elements in an array in place, returns array of deleted items
- Comparison operators of < and > work as expected
- == or === would not work as date objects would be different even if they have same time.
- A workaround would be to compare equality of
getTime()of both dates
- A workaround would be to compare equality of
- Constructor
new Date()- Uses the Timezone from the vm's box, say client in case of a browser
- Variations of constructor:
new Date(year, month, date, hours, minutes, seconds, milliseconds)- Months start at 0
- Hours are 0-23
new Date(timestampInMs)new Date("October 13, 2014 11:13:00")- Not recommended as different browsers may parse the string differently
- Methods
getTimezoneOffset(); // 300toUTCString();toTimeString();- All the methods below have their variants with set, getUTC and setUTC.
getFullYear(); // 2015getMonth(); // 0getDate(); // 1getDay(); // 0getHours(); // 0getMinutes(); // 59getSeconds(); // 33getMilliseconds(); // 100getTime(); // timestamp in milliseconds
PISQRT2SQRT1_2power(number, exp)sqrt(number)round(9.12); // 9, 9.53 => 10ceil(9.01); // 10floor(10.99); //10max(10, 2.1, 8.5, 19, 5.9); // 19min(10. 2.1, 8.5, 19, 5.9); // 2.1abs(-7); // 7random()- returns a value from 0 to 1
sin(30)cos(30)tan(30)
- Not supported by IE7
- use a json lib, say http://bestiejs.github.io/json3/
- Methods
parse("jsonString");stringify({})
- Everything by default is in
global(windowin case of browser) scope unlessvarkeyword is used. - No block scope, say if block.
- Scope resolutions starts from inner most block to global
- Lexical Scope:
- Children inherit scope data from their parents
- Closures maintain references to the used variables
// this is also a good example of how a closure works function makeGreeter(greeting, punc) { punc = punc || "!!"; return function (sender) { return sender.trim() + ", " + greeting.trim() + punc.trim(); } var hello = makeGreeter("hello"); hello("John"); // John, hello!! // hello retains references to greeting and punc var howdy = makeGreeter("howdy", "??"); howdy("Jason"); // Jason, howdy?? // howdy maintains references to its own set of variables, different from hello() // set hello and howdy to null to free up memory
- When using a variable from outer scope(specially global) a number of times, assign that to a local variable to save resolution cost.
- Do not clutter global scopes, use immediately invoked functions instead.
## Functions
- Do not care about number of arguments
- Can't define default value in signature (unless using ECMAScript6 or above, most environments use ECMAScript5 today(June 2015))
- one option would be to do
```javascript
arg = arg || "defaultValue";
but this would fail for falsey values
- safer bet is:
typeof a !== 'undefined' ? a : 42;Using !== instead of != to prevent the coercion as 1 != true is false but 1 !== true is true
- Functions themselves are objects and have methods of their own
- Every function has access to two special objects
this. For global onesthisis set to window.bind(object)to get a copy of function bound to passed object- does not work in IE8, use polyfill.
call(object[, arg1, arg2, ...])to call function on a specific object with explicit argumentsapply(object[, argumentsArray])to call function on a specific object with an array of arguments Using any of the above 3 would change the meaning ifthisinside function.
arguments- looks like an array even though it is an object, might change in future versions
- contains passed arguments even if function signature doesn't capture any
calleeproperty returns a reference of the current function. Good for recursion- it is safer than calling the function by the name as the name could change.
- Not many global functions, most functions are bound to some sort of object.
- Immediately Invoked Function or IIF:
(function () {
//code here
}());- Can use both, function declaration and function expressions
- function declaration are moved to top of the execution so we can call them before we define them. Same is not true for function expressions.
- Every call creates a new execution context. Make sure to set closure variables to null when not needed.
try {
} catch(err) {
} finally {
}- Check if a certain expected API is available, if not, provide with an implementation. Use to add missing features across different environment.
if (! String.prototype.trim) { String.prototype.trim = ...; }- Fix unique behavior of a platform to normalize same API across different platforms by intercepting calls to existing API. Used to deal with browser-specific behaviors or fix bugs.
- Common example is trying to fix the unique behavior in IE
- Used to achieve the same purpose as callbacks with more readable code, support for multiple async jobs and better error handling.
function isUserTooYoung(id) {
return openDatabase(db)
.then(getCollection)
.then(find.bind(null, {'id': id}))
.then(function(user) {
return user.age < cutoffAge;
});
}vs
function isUserTooYoung(id, callback) {
openDatabase(function(db) {
getCollection(db, 'users', function(col) {
find(col, {'id': id},function(result) {
result.filter(function(user) {
callback(user.age < cutoffAge)
}
}
}
}
}- When
then()invokes a function it passes on the last promise's resolved result to it. In the above example lastthen()gets the user object found by the 2nd lastthen(). then()can take two callbacks, first one to invoke on success of last promise and second one to invoke on failure- Error handling is much easier. Just add a
.catch(function() {});
somethingAsync()
.then(somethingElseAsync)
.then(somethingElseElseAsync)
.catch(function(error) {
console.log("Failed!", error);
})
.then(somethingDifferentAsync)
.done(finalAsync);.catch()can be added anywhere..catch()is just a syntactical sugar for:
.then(undefined, function(error) {
})- Fancy error handling:
asyncThing1().then(function() {
return asyncThing2();
}).then(function() {
return asyncThing3();
}).catch(function(err) {
return asyncRecovery1();
}).then(function() {
return asyncThing4();
}, function(err) {
return asyncRecovery2();
}).catch(function(err) {
console.log("Don't worry about it");
}).then(function() {
console.log("All done!");
});- Difference between
then()anddone()then()changes result to the return of the last promise,done()keeps it intact from the last call.
promise.then(function (x) { // Suppose promise returns "abc" console.log(x); //abc return 123;
}).then(function (x){ console.log(x); //123 }).then(function (x){ console.log(x); // undefined as the console.log in above then() didn't return anything })
vs
```javascript
promise.done(function (x) { // Suppose promise returns "abc"
console.log(x); //abc
return 123;
}).done(function (x){
console.log(x); //abc
}).done(function (x){
console.log(x); //abc
})
- Promises are resolved only once so caching is really easy for cases when we want to make single request even if there are multiple invocations.
var _cache = {};
function doSomethingCool(id) {
if (! _cache[id]) {
_cache[id] = thatSomethingCool();
}
return _cache[id];
}
doSomethingCool('123').then(...);
// Following would not call thatSomethingCool() again, instead use the cached value
doSomethingCool('123').then(...);- And about multiple async jobs
Promise.all([first(), second()]).then(function() {
// all loaded
}, function() {
// one or more failed
});setTimeout(function, speed);- returns id and calls said function once after speed ms, does not block processing
clearTimeout(timeoutId);- cancels a queued Timeout call
setInterval(function, speed);- behaves same as
setTimeout()except keeps calling the function over and over till interval is cleared.
- behaves same as
clearInterval(intervalId)
- Ways to create objects
// least common?
var person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.getFullName = function (separator) {
separator = typeof separator !== 'undefined' ? separator : " ";
return this.firstName + separator + this.lastName;
};
// commonly used when we need to set a custom prototype for the object
// being created. Custom prototype can be passed as first argument to
// createObject here
var obj = Object.create();
// most common syntax
// equivalent to: Object.create(Object.prototype)
// Properties and methods can be added directly
// inside the literal notation or outside.
// Doing it inside the literal is preferred to save
// repeating the object variable name.
var person = {
firstName : "John",
lastName : "Doe",
getFullName : function (separator) {
separator = typeof separator !== 'undefined' ? separator : " ";
return this.firstName + separator + this.lastName;
}
};
// constructor function:
// could also do: var Person = function(firstName, lastName)
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = function (separator) {
separator = typeof separator !== 'undefined' ? separator : " ";
return this.firstName + separator + this.lastName;
};
}
var person = new Person("John", "Doe");
// factory
function createPerson(firstName, lastName) {
return {
firstName : firstName,
lastName : lastName,
getFullName : function (separator) {
separator = typeof separator !== 'undefined' ? separator : " ";
return this.firstName + separator + this.lastName;
};
}
var person = createPerson("John", "Doe");- Any function can be a constructor function. Convention is to have the first letter as capital e.g function naming follows TitleCase
- When instantiating an object inside constructor we can choose to also add methods to that object. BUT, this should be done only when where the function is not supposed to change. If we bundle functions inside the constructor there is some overhead in object creation as each time we would need to create a fresh copy of those functions.
- Dot as well as array notation can be used to access object properties. Dot notation would fail if the property key is not a valid identifier, say it has spaces or it is a reserved keyword or starts with a number, ...
console.log(person.firstName);
console.log(person["lastName"]);- Each object has 2 things: key-value properties and a pointer to another object called prototype.
- Object properties' data-descriptors can be set as:
writable- self explanatory.
writable=falsewould result in readonly property.
- self explanatory.
enumerable- whether or not expose this property to the properties loop.
configurable- whether or not we allow redefinition of property with different data-descriptors
- The short hand syntax above set all three to true.
- Use
Object.getOwnPropertyDescriptor(object, "property")to get descriptors of a property.
- Objects can also have accessors (getter & setters).
var person = {};
// setting data descriptors
Object.defineProperty(person, 'firstName', {
value: 10,
writable: true,
};
// setting data descriptors
Object.defineProperty(person, 'lastName', {
value: 10,
writable: true,
};
// setting accessors for a dynamic/computed property
Object.defineProperty(person, 'fullName', {
get: function() {
return this.firstName + " " + this.lastName;
}
};- Property definitions can also be combined in one block of code using
defineProperties()
var person = {};
Object.defineProperties(person, {
firstName : {
value: 10,
writable: true,
},
lastName : {
value: 10,
writable: true,
},
fullName : {
get: function() {
return this.firstName + " " + this.lastName;
}
};- One might prefer to use functions for computed properties instead
var rectangle {
height: 10,
width: 20
};
Object.defineProperty(rectangle, 'area', {
get: function() {
return this.height * this.width;
}
};vs
var rectangle {
height: 10,
width: 20
area: function() {
return this.height * this.width;
}
};Given the context both are valid. The first case might be used where we need it as a property instead of a function. Accessors really shine when we are dealing with boolean properties so instead of:
el.setEnabled();
el.setDisabled();
el.isEnabled();we have
el.enabled = true;
el.enabled = false;
el.enabledwhere enabled would be a dynamically computed property using set and get accessors on backend.
- Enumerating Properties
for (var prop in obj)
{
console.log(obj.prop);
}or
for (var prop in Object.keys(obj))
{
console.log(obj.prop);
}- General guidelines
- Use literal notation when only one of a kind is needed
- Prefer Constructor over factory
- Attach methods to
prototypeinstead of object itself - Use
Object.defineProperties()and set proper flags, better if explicit, and do it outside constructor.
- JS does not have classes. Everything is object.
- Every function has
prototypeproperty that refers to an object that'll be used as prototype for the objects created through that function.__proto__is the actual object use for identifier resolution, whileprototypeis just available on functions and is used to initialized__proto__for the objects created using that function
function Point(x, y) { this.x = x; this.y = y; } var myPoint = new Point(); // proto isn't part of the standard yet, do not use it on production // the following are all true myPoint.proto == Point.prototype myPoint.proto.proto == Object.prototype myPoint instanceof Point; myPoint instanceof Object;
- When calling a function on an object, local functions to that variable are consulted first ( ```hasOwnProperty('methodName')```) and then the functions on its prototype and then the functions on its prototype's prototype and so on till a null is found.
- One of the difference between the locally bound functions inside constructor and the prototype one is that the prototype ones can be dynamically changed and the changes would apply to all objects (as objects store references, not the actual functions, to the functions on prototype)but the local ones are always part of the object itself.
- Prototype
- Easiest way to understand prototype is to think of constructor function as class and the prototype as a set of shared members(data and methods)
- ```Object.create(protoTypeObject)``` can be used to create a new object with custom prototype:
```javascript
(function () {
'use strict';
var Person = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.localFunction = function () {
return "localFunction";
};
};
Object.defineProperties(Person.prototype, {
"sharedProperty": {
value: 10,
configurable: true
},
"sharedPropertyThroughAccessor": {
// we could have used value: here instead. Actually that is better because this isn't like a get/set
// property. But, we have used get: here just to demonstrate that we can.
get: function () {
return "shared property through accessor";
},
configurable: true
},
"sharedMethodAsProperty": {
value: function () {
return "shared method as property";
},
configurable: true,
}
});
Person.prototype.sharedMethod = function () {
return "shared method";
};
var Employee = function (firstName, lastName, title) {
Person.call(this, firstName, lastName);
this.title = title;
this.localFunction = function () {
// localFunction can't be overridden the easy way
// not using closure around (new Person()).localFunction because
// then any changes we make to Person.localFunction() would not be
// reflected here. May be we should use closure as Person's localFunction
// is local afterall.
return (new Person()).localFunction.call(this) + " overridden";
};
};
Employee.prototype = Object.create(Person);
var sharedProperty = Object.getOwnPropertyDescriptor(Person.prototype, "sharedProperty").value;
Object.defineProperty(Employee.prototype, "sharedProperty", {
value: 11 + sharedProperty,
configurable: true
});
var sharedPropertyThroughAccessor = Object.getOwnPropertyDescriptor(Person.prototype, "sharedPropertyThroughAccessor");
// bind with Employee, else you'd get person1's properties
var sharedFn = sharedPropertyThroughAccessor.get.bind(this);
Object.defineProperty(Employee.prototype, "sharedPropertyThroughAccessor", {
get: function () {
return sharedFn() + " overridden";
}
});
var sharedMethodAsProperty = Object.getOwnPropertyDescriptor(Person.prototype, "sharedMethodAsProperty");
var sharedMethodAsPropertyFn = sharedMethodAsProperty.value.bind(this);
Object.defineProperty(Employee.prototype, "sharedMethodAsProperty", {
value: function () {
return sharedMethodAsPropertyFn() + " overridden";
}
});
var sharedMethodFn = Person.prototype.sharedMethod.bind(this);
Employee.prototype.sharedMethod = function () {
return sharedMethodFn() + " overridden";
};
var johnDoe = new Employee("John", "Doe", "Principal");
// this would log "localFunction overridden"
console.log(johnDoe.localFunction());
// this will log "21"
console.log(johnDoe.sharedProperty);
// this will log "shared property through accessor overriden"
console.log(johnDoe.sharedPropertyThroughAccessor);
// this will log "shared method overridden"
console.log(johnDoe.sharedMethod());
// this will log "shared method as property overridden"
console.log(johnDoe.sharedMethodAsProperty());
}());
isPrototypeOf()getPrototypeOf()
- No notion of namespaces
- Best we can do is create a cryptic object name and wrap everything in it
var cryptNamespace = (function() {
// code
} ());- Problem: what if cryptNamespace already exists due to some other version or a copy of script?
var cryptNamespace = (function(cryptNamespace) {
// code
return cryptNamespace;
} (cryptNamespace || {}));- window is implied for global identifiers
- three dialog boxes
alert("message")confirm("message");- returns boolean
prompt("question", "defaultValue");- returns supplied value
location- set and get operations are same for
locationorlocation.href
- set and get operations are same for
encodeURIComponents(value)- dom is slow so get elements ready before manipulating dom e.g. create element, set attributes, append/replace...
documentMethods:getElementsByTagName("tagName")- returns
NodeList, not Array, objects are live, changes are applied directly to page, new objects appear automatically
- returns
getElementById("id");- returns object
getElementByClassName("class");- returns objects
querySelector("div p");- returns the first match, #id (
getElementById()is faster for just ids)
- returns the first match, #id (
querySelectorAll("p");- returns the all matches in a
NodeList, not live.
- returns the all matches in a
createElement("tagName");- returns an element, just object, still not append to page anywhere
createTextNode("text");- does not regard html
documentObject properties and methodsparentNodetagNameinnerHtmlclassName- could assign multiple classnames separated by space.
- Wrap class names in spaces to ensure they are not concatenated to existing/future classnames, would also made replacing/removing an existing class name really easy.
- An alternate would be
classList
style- camelCase properties that have a hyphen, doesn't retrieve style attributes from css, would have to use computed styles for that
currentStyle- accessing style in legacy IE versions
offsetLeftoffsetRightoffsetTopoffsetBottomappendChild(element)insertBefore(newElement, elementOnPage)replaceChild(newElement, elementOnPage)setAttribute("property", "value");- a lot of attributes are available directly as property,
id,cssClass
- a lot of attributes are available directly as property,
classListadd("className");toggle("className");- polyfill? https://github.com/eligrey/classList.js https://github.com/remy/polyfills
getComputedStyle(elementObject, null);- 2nd argument is pseudo element match that not every browser supports,.
- Returns a
CSSStyleDeclarationobject, usegetPropertyValue("styleKey")to get value for specific style.
- DOM Level0 Event Handles:
oneventNameHere = function () {}; // e.g. onclick, onload, etc- Every browser supports them
- Can only bind one handler at a time
- Standard
addEventListener("eventNameHere", handler, capture = true);- Older browsers needed all three arguments.
- Last argument is if we want to use capture(document -> body -> .. -> target) or bubble(target -> ... -> body -> document).
- W3C standardized by merging them e.g. capture -> target -> bubble.
- Recommended to use false to use bubbling as IE8 low do not support capturing.
- A single parameter is passed to handler e.g.
event.eventhas useful properties liketypeandtarget, mostly used for event delegation though. Oh and our favoritepreventDefault()too.
- Older browsers needed all three arguments.
removeEventListener("eventNameHere", handler, capture = true);- Needs exact same params to remove any handler as when we added listener for it.
- Declaring same anonymous function won't work as each function declaration is a new object.
- Legacy IE (IE8 and below)
attachEvent("onEventNameHere", handler);- No third argument as IE8 and below only support bubbling
- global
eventobject is created for every event which gets created withtype,srcElementand other data about the event. event.returnValue = falseinstead ofevent.preventDefault()
detachEvent("onEventNameHere", handler);
keydown|keyupevent.keyCode; // works in all browsers, case insensitive so assumed all keys to be capsevent.altKey,event.ctrlKey,event.shiftKey
keypress(does not happen for modifier keys)- standard browsers:
event.charCode; // ascii code of the key pressed - legacy IE:
event.keyCode; // ascii code of key presed
- standard browsers:
- Compromise event trigger performance for event binding performance.
- Event Delegation when done badly could also cause unexpected events being triggered from newly added elements even though we didn't bind any events to them yet.
- It could also lead to if-else-if-else-if-else-if-else-if-else-if-else-if-else-if-else inside the handler.
- WITH GREAT POWER COME GREAT RESPONSIBILITIES.
- Use bubbling
- Attach event to a wider scope, get the event target and then based on target behave differently
- Forms
elementssubmit()- does not trigger submit event.
- ``reset()```
- Input Elements
valuetypedisabledfocus()
- Text Elements
select()
- Select Lists
remove(index)- Adding a new option
var opt = new Options("Text", "value"); // following would add opt before the current 2nd entry in the list select.add(opt, select.options[2]);
- Finding selected option
- Old Style
- ```selectedIndex```
- ```options```
- Future
- ```selectedOptions```
- Checkboxes/Radio Buttons
- ```checked```
## AJAX
- ```XMLHttpRequest```
- would not work on IE though :P
- ```onreadystatechange = function () {}```
- ```readyState; // state notifications for async, 4 == ready```
- ```status; // http response status code, ok = [200-299,304] ```
- ```open("REQUEST_METHOD", "URL", async = true)```
- ```setRequestHeader("HeaderName", "HeaderValue");```
- Common use case is to set ```Content-Type``` header to ```application/x-www-form-urlencoded``` or ```application/json``` etc
- ```send(postData = null)```
- ```responseText```
- ```responseXML; // would contain xml object if response was xml```
## Local Storage
- **NOT** cookies
- Data stored is local to the domain that set it
- Not supported in IE7
- key-value store
- Values are always stored as string.
- Use JSON to store objects.
- ```localStorage```
- Global object available on window
- Methods
- ```setItem("key", "value");```
- could also set it as a direct property
- ```getItem("key");```
- could also access it as a direct property
- ```removeItem("key");```
- ```clear()```
# Misc
-
```javascript
var globalGetFullName = function (separator) {
separator = typeof separator !== 'undefined' ? separator : " ";
return this.firstName + separator + this.lastName;
};
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = globalGetFullName;
}
// a is the actual function, a is a copy of constructor and can be used to construct objects
var a = Person;
// b is undefined, not using new
var b = Person();
// c is same as b, except that now we have function in place, c is also undefined
var c = (function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = globalGetFullName;
}());
// d is new person object with undefined as both properties
var d = new Person();
// e if a new person object with both properties set correctly
var e = new Person("Jane", "K");
// factory
function createPerson(firstName, lastName) {
return {
firstName : firstName,
lastName : lastName,
getFullName : globalGetFullName
};
}
// l is a copy of factory and it can be create to construct objects
var l = createPerson;
// m is a option with both properties set to undefined
var m = createPerson();
// n is same as n, except function is executed in place, n is also undefined.
var n = (function createPerson(firstName, lastName) {
return {
firstName : firstName,
lastName : lastName,
getFullName : globalGetFullName
};
}());
// o is an object(a copy of actual object created by factory?) with both properties set.
var o = new createPerson("first", "last");
- node wraps all code files in iif
- Use nodemon to simulate live-reload in node
- Most callbacks in node take a callback with request and response object, in that order.