npm install
npm link babel-cli
See the ECMAScript standard by TC39, ECMA-262
The JSON standard can be found at ECMA-404
JavaScriptwas first calledMocha, thenLiveScript- First announced in December, 1995
- First released in Netscape Navigator 2.0 in March, 1996
- Delivered to standards body
Ecma Internationalin November, 1996 - Categorized as
ECMA-262under working groupTC39 - Release timeline
es1was adopted in June, 1997es2was adopted in June, 1998es3was adopted in December, 1999- The 4th edition was never published
es5was adopted in December, 2009es5.1was adopted in June, 2011es6, officiallyES2015, was adopted June 2015es7, orES2016, is small and will only contain 2 new featuresES2017draft spec- github/tc39/ecma262 official
- es 5.1 implementations
SpiderMonkey, used in Firefox with theGeckolayout engineV8, used in ChromeJavaScriptCore (Nitro), used in WebKit, SafariChakra, used in Microsoft EdgeJScript, used in IE with theTridentlayout engineRhino, used in Java
Highlights:
- if a construct is not optimizable, the entire containing function becomes unoptimized
- this is true even if the code is unreachable
- if necessary, isolate such code to a minimal function
- currently not optimizable (in the major vms)
- functions with
try{} catch{}ortry{} finally{} - functions containing object literal having
.__proto__- e.g. as might be done with es6 object literal initializers
- functions containing object literals having
getorsetproperties - functions with
eval() - functions with
with() {} - functions containing
debugger
- functions with
- leaking
argumentsargumentsobject must not be leaked OR passed() => arguments[].slice.call(arguments)- Only use
argumentswith.lengthor[i]whereiis a valid integer index intoarguments- i.e. index cannot be out of bounds
fn.apply(y, argumentsis a special case and is OK
for...inwith 'non-local' key- the referenced 'key' must be a 'pure local variable'
- don't do
var key; var f=(obj)=>{for (key in obj)} - don't do
var f=(obj)=>{for (var key in obj){}; return ()=>key;}
- don't do
- the referenced 'key' must be a 'pure local variable'
- iterating over non
simple enumerableobjects- non
simple enumerableis one using properties that aren't valid identifiers - this results in
hash table modeordictionary mode, backed by a hash table - this includes objects containing a property that is an
array index(a.k.a. an element)- never use
for...inwith anArray function() { var a=[1,2]; for (var i in a) {} }will not be optimized- if necessary, use
Object.keys(a)with a regularforloop
- never use
- non
hash table mode- when re-structuring an object
- don't use
delete- prefer assignment to
undefined
- prefer assignment to
- don't dynamically add properties after initialization
- prefer a fully predefined structure via constructor or object literal assignment
- don't use
- when using properties that aren't
valid identifiers- e.g.
{'-': 3}
- e.g.
- when an object has
enumerable propertiesin itsprototype chain- e.g.
Object.prototype.fn = function() {}
- e.g.
- when re-structuring an object
- variables are loosely typed, not statically typed
- variables can be assigned and reassigned to values of different types
- variable declarations are hoisted to the top of their function scope
- for function declarations
- the function declaration and definition are hoisted
- for all variable declarations
- the variable declaration is hoisted, but not the assignment
- this includes function expression definitions
- the variable declaration is hoisted, but not the assignment
function outer() {
a(); // -> "a"
b(); // -> TypeError: b is not a function
// for this function declaration,
// both declaration and definition are hoisted
function a() {
console.log("a");
}
// for this variable declaration,
// only the variable declaration is hoisted
var b = function() {
console.log("b");
}
}- built-in basic data types such as String (as returned from
typeof)- Note:
instanceofcan be used to check constructor types that are not of the basic types string,number,boolean,null,undefined,object, (function)stringis a special case- a string literal primitive is not an object
typeof('abc') === 'string' // true'abc' instanceof Object // false
- a string literal can be used as if it were an object
'abc'.substring(1) // -> 'b- the js runtime autoboxes the string literal to a String object to perform the operation
'abc'.substring(1)is logically equivalent tonew String('abc').substring(1) // -> 'bc'String.substringreturns a string literal, not a new String object
- a string literal primitive is not an object
number,boolean,stringliteral primitives can be autoboxed(1).toFixed(2) // '1.00'true.valueOf() // true'abc'.indexOf('b') // 1
nullis a special case- a global primitive property that has a formal type of
objectbut with no properties or methods - it is not itself an instance of any
Object - it is a value that represents
the absence of an object - a variable assigned to the value
nullis not a reference to anything typeof (null) === 'object' // truenull instanceof Object // falsenull === null // trueNumber(null) // 0
- a global primitive property that has a formal type of
undefinedis a special case- a "primitive" value that has the formal type of
undefined - it is not an object
typeof(undefined) === 'undefined' // trueundefined instanceof Object // falseundefined === undefined // trueNumber(undefined) // NaN
- a "primitive" value that has the formal type of
NaNis an especially special casetypeof (NaN) === 'number' // trueNaN instanceof Number // falseNaN === NaN // falseNaN == NaN // falseisNaN(1) // falseisNaN("a") // true
functionis a special case- a function is a regular object with the additional capability of being
callable typeof (function(){}) === 'function'- a function literal of typefunction(function(){}) instanceof Object // true(function(){}) instanceof Function // true
- a function is a regular object with the additional capability of being
new function(){}creates a new object via the function literal's constructor- returns
{}- a plainobject typeof (new function(){}) === 'object'(new function(){}) instanceof Object // true(new function(){}) instanceof Function // false
- returns
- Note:
- javascript primitive data types
string,number,boolean,null,undefined- primitives are discrete types
- simple value types as opposed to complex object types
- javascript
objectdata type- an object is a key/value (hash) data structure
- a function is a callable object, so some objects are functions
- objects that are
functiontypes can be constructors withnewtypeof Object === 'function' // truetypeof Number === 'function' // truetypeof String === 'function' // truetypeof Boolean === 'function' // truetypeof Array === 'function' // true
- objects that are
- note that object prototypal "inheritance" is delegative OLOO (objects linking to other objects)
({}).__proto__ === Object.prototype // true
- built-in objects
String,Number,Boolean- these provide the prototype for "instance wrappers" around the associated primitive types
- String methods
charAt,indexOf,concat,split,slice,substring,toLowerCase,startsWith,trim- regex:
match,replace,search
Array,Function,Object,RegExp- An instance of Array is a regular object having integer key properties that have a relationship to its
lengthproperty- the integer key properties act as a numbered index
Arraytype checkingvar arr = []arr instanceof Array // truearr.constructor === Array // trueArray.isArray(arr) // true
- An instance of
Functionis a callable object- can be called/invoked as a function (to execute arbitrary work)
- can be used with the
newoperator as a constructor to return a new object of the given typevar Person = function() {}; var me = new Person()
- within the function,
var foo = function bar() {}, call usingfoo(),bar() - do not use
arguments.callee- not supported in strict mode. Use the function name.
Objectconstructornew Object()returns the empty object{}new Object(1)returns a new Number objectnew Object(1) === new Object(1) // falsetwo new objects that happen to have the same valuevar a = new Number(1); new Object(a) === new Object(a) // trueeach returns the objecta
Object.freeze()var a = {p:1}; Object.freeze(a)-pcannot be modified or extended
Object.preventExtensions()var a = {p:1}; Object.preventExtensions(a)-pcan be changed butqcan't be added
- Object creation by copying (shallow clone) an object (not prototypal inheritance)
var b = Object.assign({}, a)copies own properties fromato target and returns the target
- Object creation with prototypal inheritance
function Shape() {this.x=0, this.y=1}Shape.prototype.move = function(x,y) {this.x += x; this.y += y;}function Rectangle() {Shape.call(this)}Rectangle.prototype = Object.create(Shape.prototype)Rectangle.prototype.constructor = Rectanglevar r = new Rectangle(); r.move(1,1)
- RegExp literal expression
- start and end with
/ var r = /ab+c/r instanceof RegExp // true
- start and end with
- An instance of Array is a regular object having integer key properties that have a relationship to its
- in operator
x in objchecks ifxis a property ofobj, regardless of the enumerable flagfor (var x in obj)gets only enumerable properties (own and inherited)
- comma operator
for (var i = 0, j = 9; i <= j; i++, j--){}
deleteoperatorvar obj = {a:1}; delete obj.a;- See delete on MDN
- NOTE:
deletehas a degenerative v8 optimization penalty
- void operator
void(0)
- spread operator
var a=[1,2,3]; var b=[0, ...a] // b: [0,1,2,3]var f = (x,y,z) => x + y + z; f(...a); // calls f(1,2,3) --> returns 6
- an object literal is an
Objectvar a = {}is a shortcut for the constructor functionvar a = new Object(){}.__proto__ === Object.prototype // true{}.constructor.prototype === Object.prototype // true- whereas
Object.create(null)inherites from nothing Object.create(null).__proto__ // -> undefined
- consider properties to be like variables attached to an object
- a property can be an identifier, string literal, or a number
- a property that is not a valid identifier can only be accessed via bracket notation
var a = {a:1, 20:"twenty", "":"empty", "@-^": "works"}a.a // 1a[20] // 'twenty'a["20"] // 'twentya[""] // 'empty'a["@-^"] // 'works'
- add a property using
definePropertyvar a = {}Object.defineProperty(a, 'p', {configurable:true, enumerable:true, writable:true}) // {p: undefined}Object.defineProperty(a, 'p', {configurable:true, enumerable:true, value:'val'}) // {p: 'val'}- by default, the prop will be immutable and not enumerable (excluded from
for...inloop andObject.keys())Object.defineProperty(a, 'p', {}) // immutable
- object property enumeration
for...inloops over all own enumerable properties and in prototype chain- use
obj.hasOwnProperty(key)to check for only own properties Object.keys(obj)array of all own (not in prototype chain) enumerable property namesObject.getOwnPropertyNames(obj)array of all own property names (both enumerable and not)- note that while
for (var x in obj)gets only enumerable propertiesx in objsimply checks ifxis a property of obj, regardless of the enumerable flag
- get object property descriptors
- to determine
configurable,enumerable,writable,value Object.getOwnPropertyDescriptor(obj, prop)- See this jsbin
- to determine
- create an object of a given type without a constructor function
var Phone = {brand:"generic", getBrand: function() {console.log(this.brand)}}var iphone = Object.create(Phone);iphone.brand = "iphone"iphone.getBrand() // iphone- [jsbin example]{http://jsbin.com/jiruva/1/edit?js,console}
- getters and setters
var a = {a: 1, get propA() {return this.a}, set propA(x) {this.a = x}}a.a // 1a.propA // 1a.propA = 100a.a // 100
- object literals in ES2015 (es6)
- can declare the target prototype, equivalent to the imperative
Object.create(targetProtoObject) - can use compact function notation
- can use computed property names
- can declare the target prototype, equivalent to the imperative
var obj = {
// __proto__
__proto__: targetProtoObject,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
- An array is of type '
object' but is printed as '[]' as opposed to '{}'- An Array is an iterable object with index keys and a length property
- es6 array iterators have a
.next()methodvar a = [10,20,30]var aIter = a.keys()aIter.next().value // -> 10
- An iterator
a.keys()is sparse (doesn't skip holes);Object.keys()is densevar a = [10,,20,,30,40]contains two elisions ata[1]anda[3][...a.keys()] // -> [0,1,2,3,4,5]Object.keys(a) // -> ['0', '2', '4', '5']
Array.forEach()visits each element in the array, as opposed to each index.var a = [10,,20]- will visit
a[0]anda[2], as there is no member aa[1]
- Check if an object is an array
Array.isArray(obj)obj instanceof Array
- An array literal is a kind of object initializer
- Extra commas in array literals
var a = [1,2,,4,5,,,]- the unspecified elements will be
undefineda[2] // undefinedObject.keys(a) // [ '0', '1', '3', '4' ]
- the last of any trailing commas is ignored
a.length // -> 7[10,].length // -> 1[10,,].length // -> 2
- The
lengthproperty- setting length can resize an array
var a = [1,2]a.length // 2a.length = 5 // -> [1, 2, , , ]a.length = 1 // -> [1]
- The
argumentsobject of a regular function is an 'array-like' object that prints{}.- It can be converted to a proper array with
Array.from(arguments)(es6) Array.slice(arguments,0)(es5) also works but is not recommended- (via MDN) "You should not slice on arguments because it prevents optimizations in JavaScript engines (V8 for example)"
- It can be converted to a proper array with
- An array-like object is an iterable object and can be converted to a proper Array
Array.from({'0':10, '1':20, 'length':2} ) // -> [10,20]Array.from({'0':10, '1':20}) // -> []
- Array prototype methods may alter or create. '
shift' alters, whereas 'slice' creates.- some methods that return a new array
.concat(),.slice(),.filter(),.map(),.reduce()- note that while
.map()doesn't alter the original array, it can be modified from the callback functionfn(curVal,i,origArray)
- some methods that alter the array
.shift()- returns the removed (head) element.unshift()- returns the new length of the array.splice()- returns the removed elements (in an array).reverse()- returnsundefined.sort()- returnsundefined
- some methods that return a new array
babel-node code/arrays.js
- Arrow functions inherit
thisfrom the enclosing context, also known as 'lexical' or 'static' context. The 'this' reference is not dynamically determined and is not observed when supplied from abind,call, orapplymethod.- A regular function that isn't already bound can be re-wired to a different object.
- An arrow function is equivalent to
function() {}.bind(this)that is statically bound and cannot be re-bound
- Arrow functions do not get their own
argumentsobject. - Since arrow functions don't get a proper
arguments, use a 'rest' parameter instead.- Note that arrays and 'rest' objects can be used to 'spread' out as parameters to another function invocation.
- Use parentheses to return an object literal when using concise syntax
let f = () => ({ a: 1});// without parens, it's just a function block without a return statement and returnsundefined.
babel-node code/arrow-functions.js
- Function declaration vs function expression
- A function declaration gets added to the execution context's 'variable object'
- In the global context,
function f() {}; "f" in window // -> true
- In the global context,
- A function expression is evaluated inline
(function f() {}); "f" in window // -> false
- A function declaration gets added to the execution context's 'variable object'
- Function currying reduces the 'arity' of a function into an invocation chain of unary functions
- Partial application reduces the 'arity' of a function by binding (applying) some parameter values
- Use default params to change the 'arity' of a function for partial application
- Use
Function.prototype.bindto define leading args (es5)var f = function (a,b,c) {return a+b+c}var g = f.bind(null,1,2)g(3); // returns 6- or use a fat arrow to create an unary function
var g = c => f(1,2,c);
- Use default trailing parameters (es6)
- Use
- example of currying
var f = function(x,y) {return x+y}var g = function(x) { return function(y) {return x+y}}f(2,3) // -> 5g(2)(3) // -> 5
babel-node code/functions.js
- a traditional class is an abstract definition used to "instantiate" or "realize" a concrete object
- an es6 class is syntactic sugar over the prototype model
- classes are not hoisted (whereas functions are)
// class declaration
class Father {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
// class expression
const Father = class {
...
}
class Son extends Father {
getName() {
return super.getName() + " Jr.";
}
}
var boy = new Son("Jack");
boy.getName(); // -> "Jack Jr."- a prototype is an existing object that acts as a template to initialize a new object
var P = function() {this.test = 500}var b = new P()- creates an object from the constructor function of
P bis a new object, initialized to the value{test: 500}b.__proto__ === P.prototypenow b has a pointer toPbhas its own object value but also inherits fromPb.__proto__can be assigned to another parent,b.__proto__ = Q.prototype.prototypechanges are dynamic and visible to all childrenvar c = new P()P.prototype.hi=10b.hi === 10 && c.hi === 10 // true
- creates an object from the constructor function of
- use
Object.createvar a = {hi: function() {return "hi"}}var b = Object.create(a)b.__proto__ === a // trueb.hi() // -> "hi"
- create a type hierarchy
var Animal = function() {this.alive = true}var Mammal = function() {Animal.call(this); this.warm = true}var dog = new Mammal()dog.alive && dog.warm // true
- A variable can be undefined, and a value can be undefined
var a// a declared, b not declaredtypeof(a) // 'undefined'typeof(b) // 'undefined'a == null // trueb == null // in strict mode throws ReferenceError: b is not defined
for...of(es2015) - likefor...inbut iterates over the property values instead of the keys- strict mode
- place
use strictat the head of a file - or place
use strictat the beginning of a function - do not concatenate mixed strict and non-strict files (whichever is first wins)
- place
- template strings
- string literals with embedded expressions
var num = 22var t = `the number is ${num}`
letand Temporal Dead Zoneconsole.log(foo)let foo=1foois hoisted to the top of its scope, but it is unrecognized until the declaration- the above will throw a
ReferenceError - the region between the hoisted position and the declaration is known as a
TDZor Temporal Dead Zone
- the above will throw a
- Promises
var p = new Promise(function (resolve,reject){ if (success) resolve(data) else reject(reason) });- jsbin XMLHttpRequest example
- MDN reference and examples
- async/await
- a function can be marked
async - the function can then
awaita Promise - the function can be written in synchronous style
- the function is still async, so can't return the outcome of the Promise
- codepen async/await
- a function can be marked
- Generators, Iterables, Observables
- TBD
- destructuring
- Given:
let arr = [1,2,3]; - Then -
let [el1, el2] = arr;is equivalent tovar el1=arr[0], el2=arr[1]; - Given:
let obj = {p:1, q:2, r:3}; - Then -
let {p, q} = obj;is equivalent tovar p=obj.p, q=obj.q;
- Given:
setTimeoutvssetIntervalsetTimeout- will be called after some specified delay
- a blocking operation can further delay the execution
- a nested setTimeout will occur in
delay + block + execution + delay + block - the calls do not 'stack up'
- there will not be a flurry of calls
setInterval- will be queued every
nmilliseconds - a blocking operation that spans multiple intervals will enqueue at most 1 call
- the delay between calls is not guaranteed
- if a call is queued, it may execute near the next scheduled call
- it could be more or less than the specified delay
- there will not be a "flurry" of calls
- will be queued every
- http://2ality.com/2015/01/es6-destructuring.html
- Execution context
- an object used to track progress of the associated code
- can be global ec, function ec, eval ec
- maintained on a stack, with the "global ec" at the bottom and the "active ec" at the top
- an execution context contains
- variable object - vars, function decl, args
- scope chain - Variable object + parent scopes
- this value - Context object
- Variable object
- contains variables, function declarations
- in the browser global execution context, the Variable object is the global
windowobject - in a function call (activation), an object, known as an Activation object is created
- the Activation object is used as the Variable object for the function context
- it is a Variable object augmented with the function's formal parameters and
argumentsobject
- Scope chain
- like a prototype chain, a scope chain is a chain of scope objects
- in an execution context, the Scope object is the Variable object
- resolving a variable starts in the own scope (Variable/Activation object)
- lookup continues up the chain of parent variable objects, ending at the global scope
- free variables (non-local variables) require scope chain lookup
- a scope chain is the set of own and parent Variable objects
- a scope chain consists of linked scope objects
- a variable lookup implies a prototype chain search for each scope link
- a scope object may include dynamically added material (e.g. with objects)
See Below:
- in the
withblock, local scope is that of{}xis not found in that local scopexis sought up the prototype chain and is found atObject.prototype- the search for
xdoes not proceed up the scope chain wherexhas the value100 - a scope search exhausts the local scope object's prototype chain before proceeding along the scope chain
- a scope search does a
__proto__lookup before a__parent__lookup
// the 2-dimensional prototype and scope chain lookup
// can lead to unexpected behavior outside of strict mode
Object.prototype.x = 10; // top of prototype chain
var x = 100; // top of scope chain
with ({}) {
console.log(x); // prints 10, not 100
}
console.log(x); // prints 100, not 10- Closures
- closures are meant to handle the funargs (functional arguments) problem
- there are two flavors of funargs problems, upward, and downward
- upward refers to how free variables are resolved when a function is returned from a function
- the inner function saves the parent scope chain at the time of creation
- this kind of scope is known as static or lexical scope
- downward refers to how a function resolves an ambiguous identifier
- given a local and global variable, the static scope at the time of function creation is used
- this is the same lexical scope behavior as above
- a function, together with its saved static/lexical scope chain is the definition of a closure
- since all functions save lexical scope at creation, all functions are closures
- a function has a static/lexical scope chain known and saved at the time of creation/definition
- this is used to resolve free variable lookups
- the combination of the function and its scope chain form a closure
// when a function is created, the current lexical scope is saved with the closure
var a = 10;
function f() {
return a;
}
function g() {
var a = 100;
return f();
}
g(); // -> returns 10function x() {
var b = 50;
return function() {
return b;
}
}
var fx = x();
var b = 500;
fx(); // -> returns 50- this value
thisis another property of an execution context- it is the context object against which an execution context is activated
- the value of
thisis determined when entering the execution context - in the global execution context,
thisis the global object and so equals the Variable object - in a function context, the value of
thisdepends on how the function is activated/called - if a function is a property of an owner object and activated via method call, then
thisis the owner object - if a function ref is disassociated from any object and then activated,
thisis the global object- unless the function was previously bound to some context object
- as with Function#bind
- or by the implicit binding of an arrow function
- unless the function was previously bound to some context object
function f() {
let context = {
val: 10,
fn: function() {
return () => this.val;
}
}
return context.fn();
}
let x = {
test: 100,
arrow: f.fn()
}
let theArrow = x.arrow;
theArrow(); // -> 10, because the arrow function is innately bound to and thus activated against 'context'- the language core information was extracted from Dmitry Soshnikov's javascript blog
- flatten an array using recursive reduce
babel-node code/reduce.js - find two numbers in an array that sum up to an input value
babel-node code/two-sum.js
- circular references aren't garbage collected in IE, leading to memory leaks
- use polyfills to support older browsers
- use transpilers (e.g. babel) to compile es6 down to vanilla js
- use event delegation, e.g.
$(document).on( "click", "#selector", function() {}); - interesting difference in the treatment of an explicit vs implicit variable on the global object
var a=1;
b=1;
window.c=1;- for the above
- all three will add a property to the global window object
- but
ais not configurable - i.e. does not allowdeletefrom the global object - See this jsbin
- web events
-
vm turn
- one cycle through the js event loop
-
Functional Programming
- Pure functions - idempotent, free of side effects, avoids shared/mutable data
- First class functions - first class citizens and can be passed around
- Higher order functions - functions that take or return other functions
- Encourages immutability and loose coupling; avoids inflexible class hierarchies
-
Prototypal Inheritance
- Favors delegation/composition over class inheritance
- Instances inherit directly from other objects (OLOO - objects linked to other objects)
- Achieved using function constructors with
newor viaObject.create(somePrototype)
-
Concatenative (or Selective) inheritance
- Mixin composition from one of more source objects
- See Object.assign()
-
Exemplar Prototypes
- Used for flexible cloning as a means of "concatenative inheritance" instead of rigid class libraries
- Memoization
- An optimization technique that saves calculated results in a lookup table for repeated access
- Example:
code/two-sum.js- Given an array of integers, find two numbers such that they add up to a specific target number
- Avoid the O(n^2) nested loop
- Use a single pass O(n) loop storing candidates in a map by key
value2 = target - value1for lookup matching of subsequent entries
- Virtual DOM
- Memory structure for staging DOM changes
- Performs an efficient before/after diff (a.k.a reconciliation in React)
- Minimizes expensive DOM updates and thus reduces browser DOM reflow churn
- Utilizes synthetic events to allow event listeners to run without incurring the cost of browser event propagation
- Conceptually similar to double-buffering in game programming
- es6 features
- es6 equivalents in es5
- VerbalExpressions - Use common language expressions to compose RegEx
- front end developer questions - 20k github stars
- most starred github projects
- javascript framework resources - 50k github stars
- postman commandline
- v8 optimization killers
- 30 seconds of code
- 10 Interview Questions Every Javascript Developer Should Know - by Eric Elliott
- The javascript job market
- The es6 conundrum
- leetcode mockinterview
- Job search technical interviewing
- Intervews: CS/Algos vs engineering - Hacker News
- Interview process at Stripe
- Inside V8 with Lars Bak
- grunt, gulp, webpack
- javascript the core, by Dmitry Soshkinov
- Cognates - words that have the same etymological origin (from Latin
cognatus, meaningblood relative)- Example -
memoize&memorize
- Example -
https://en.wikipedia.org/wiki/Cognate#/media/File:Etymological_Relationships_Tree.png
