these are just some notes i took while i was taking the ecmascript2015 class in codeschool. i hope i can use my notes someday
############################################################ 3.8
OBJECT INITIALIZER SHORTHAND 1:59

from:
object(fName:fName,lName:lName,fullName:fullName};

to:
object(fName,lName,fullName};

WHEN THE PROPERTIES HAVE THE SAME NAME AS THE VARIABLES

ANOTHER EXAMPLE:
let naem = "sam'
let age = 45;
let friends = ['brook','tyler'];

let user = {name,age,friends};
console.log( user.name);
console.log( user.age);
console.log( user.friends);

CONSOLE OUTPUT:
sam
45
['brook','tyler']
############################################################ 3.8

OBJECT DESTRUCTURING 3:19

let user = buildUser('sam','william');

let first = user.first;
let last = user.last;
let fullName = user.Fullname;

console.log( user.first);
console.log( user.last);
console.log( user.Fullname);

NOW THE SHORTER WAY TO DO THE SAME FROM THE ABOVE:

let { first, last, fullName} = buildUser('sam','william');
console.log( user.first); // sam
console.log( user.last); // william
console.log( user.Fullname); // sam william

NOTE: you dont have to select all properties, you can select one or two or whichever properties you want, in the below
we only want the full name so wi do like this:

let {fullName} = buildUser('sam','william');

console.log( user.Fullname); // Sam William

############################################################ 3.8
ADDING A FUNCTION TO AN OBJECT 4:24
IN PREVIOUS VERSIONS OF JAVASCRIPT, ADDING A FUNCTION TO AN OBJECT REQUIRED SPECIFYING
THE PROPERTY NAME AND THEN THE FULL FUNCTION DEFINITION (INCLUDING THE FUNCTION KEYWORD)

// N O T E : FROM THIS POIN ON, I ACUTALLY TESTED THIS CODE, THE ABOVE CODE WAS NOT TESTED

############################################################ 3.8
TEMPLATE STRING: 6:00
template string are STRING LITERALS allowing embedded expressoins. this allows for a
much better way to do STRING INTERPOLATION

FROM:
function buildUser(first,last,postCount){
	let fullName = first + ' ' + last;
	const ACTIVE_POST_COUNT = 10;
}

TO:
function buildUser(first,last,postCount){
	let fullName = `${first}  ${last}`;
	const ACTIVE_POST_COUNT = 10;
}
############################################################ 3.8
WRITING MULTIPLE LINES STRINGS 6:10

let userName = "Sam";
let admin = { fullName: 'Alex Williams'};
let veryLongText = `Hi ${userName},
this is line two

this is line four

Regards,
${admin.fullName}`;

console.log(veryLongText);

OUTPUT:
Hi Sam,

this is line two



this is line four


Regards,

Alex Williams

############################################################ 3.9
############################################################ 3.9
DOUBLE PIPES: 2:45
// http://stackoverflow.com/questions/2802055/what-does-the-construct-x-x-y-mean
var title = title || "This is the Title";
console.log(title); // This is the Title

############################################################ 3.9
MERGIN VALUES WITH object.assign
I AM NOT SURE I UNDERSTAND THIS YET



############################################################ 4.1
ARRAYS
ASSIGNING FROM ARRAY TO LOCAL VARIABLES:

OLD WAY:
let users = ['sam','tyler','brook'];
let a = users[0];
let b= users[1];
let c = users[2];
console.log(a,b,c); // sam tyler brook

NEW WAY:
let users = ['sam','tyler','brook'];
let[a,b,c] = users;
console.log(a,b,c); // sam tyler brook

LETS SAY IF YOU DONT WANT THE SECOND NAME (tyler)

//you can do this:
let users = ['sam','tyler','brook'];
let[a, ,b] = users;
console.log(a,b); // sam  brook
############################################################ 4.1
ARRAYS
COMBINING DESCTRUTING WITH REST PARAMS: 2:28

let users = ['sam','tyler','brook'];
let[first, ...rest] = users;
console.log(first, rest); // sam ["tyler", "brook"]
############################################################ 4.1
ARRAYS
DESTRUCTIONG ARRAYS FROM RETURN VALUES: 2:51

function activeUsers(){
	let users = ['sam','tyler','brook'];
	return users;
}
let active = activeUsers();
console.log(active); // ["sam", "tyler", "brook"]

// when returing arrays from functions, we can assign to multiple variables at once. 3:35
function activeUsers(){
	let users = ['sam','tyler','brook'];
	return users;
}
let [a,b,c] =  activeUsers();
console.log(a,b,c); // sam tyler brook
############################################################ 4.1
LOOP
using for .... of lto loop over arrays 3:55

OLD WAY:
let names = ['sam','tyler','brook'];
for(let index in names){
	console.log( names[index] );
	/* OUTPUT:
sam
tyler
brook
	*/
}
THE FOR..OF STATEMENT ITERATES OVER PROPERTY VALUES, AND ITS BETTER WAY TO LOOP OVER ARRAYS AND AOTHER ITERRABLE OBJECTS.

NEW WAY: (SAME OUTPUT)
let names = ['sam','tyler','brook'];
for(let name of names){
	console.log( name);
}
/* OUTPUT:
sam
tyler
brook
*/

// YOU CANNOT USE FOR.. OF FUNCTION ON OBJECTS, IF YOU DID  YOU WILL GET AN ERROR THAT SAYS:
/// TypeError: post[Symbol.iterator] is not a function
// this is how the code looks like when this error is generated: : 5:08

let post = {
	title: 'new features in Javascript',
	replies: 19,
	lastReplyFrom: 'sam'

};
for(let property of post){
	console.log( 'Value: ', property);
}

// THE ERROR THAT I GOT SAYS:
Uncaught TypeError: post[Symbol.iterator] is not a function(…)

to avoid this error, you can check if its a function: for example this code:

let names = ['sam','tyler','brook'];
console.log( typeof names[Symbol.iterator]); // function
for(let name of names){
	console.log( name);
}
/* OUTPUT:
function
sam
tyler
brook
*/

the following will show 'undfined'

let post = {
	title: 'new features in Javascript',
	replies: 19,
	lastReplyFrom: 'sam'

};
console.log( typeof post[Symbol.iterator]); // undefined
for(let property of post){
	console.log( 'Value: ', property);
}

// THIS IS HOW YOU FIX THE ABOVE:
############################################################ 4.1
:FINDING AN OBJECT IN AN ARRAY: 7:03
// how can you find admin in this array?
let users = [
	{ login: 'sam',	admin:false},
	{ login: 'brook',	admin:true},
	{ login: 'tyler',	admin:false},
];
//let admin = users.find( (user) => {
	//return user.admin; // returns the first object for which user.admin is true
//})
// OR YOU CAN USE THIS SHORTER ONE LINER ARROW FUNCTION
let admin = users.find( user => user.admin); // OUTPUT THE SAME: Object {login: "brook", admin: true}
console.log( admin); // Object {login: "brook", admin: true}


############################################################ 4.8
DATA MAP STRUCTURE
MAPS ARE DATA STRUCTURE COMPOSED OF A COLLECTION OF KEY/VALUE PAIRS. THEY ARE VERY USEFUL
TO SOTRE SIMPLE DATA SUCH AS PROPERLTY VALUES

SOME ISSUES WITH USING OBJECT AS MAPS 0:52
WHEN USING OBJECTS AS MAPS, ITS KEYS ARE ALWAYS CONVERTED TO STRING

EXAMPLE:
// TWO DIFFRENT OBJECTS HERE
let user1 = { name: 'sam'}; // doesnt visit the site very often
let user2 = { name: 'tyler'}; // has 42 replies, is very active

let totalReplies = {};
totalReplies[user1] = 5;
totalReplies[user2] = 42

// WE GET THE SAME OUTPUT FOR THE TWO DIFFERENT OBJECTS
console.log( totalReplies[user1] ); // 42
console.log( totalReplies[user2] ); // 42
// IF WE FOR THE TOTAL KEYS IN THE totalReplies object, WE GET ["[object Object]"]
console.log( Object.keys(totalReplies) ); // ["[object Object]"]

// TO AVOID THIS, YOU SHOULD STOP USING OBJECT AS MAPS IN JAVASCRIPT AS OF NOW!!!!!!!!!!
// AND START USING A NEW DATA STRUCTURE CALLED MAP

HOW DO WE FIX IT?
############################################################ 4.8
DATA MAP STRUCTURE: 3:00
// STORING KEY/VALUES WITH MAP
// THE MAP OBJECT IS A SIMPLE KEY/VALUE DATA STRUCTURE. ANY VALUE MAY BE USED AS EITHER A KEY OR A
// VALUE AND OBJECTS ARE NTO CONVERTED TO SRING
let user1 = { name: 'sam'}; // doesnt visit the site very often
let user2 = { name: 'tyler'}; // has 42 replies, is very active

let totalReplies = new Map();
totalReplies.set( user1,  5); // USE THE  set() METHODS TO ACCESS THE VALUES IN Maps
totalReplies.set( user2,  42);// USE THE  set() METHODS TO ACCESS THE VALUES IN Maps

// USE THE get() METHODS TO ACCESS THE VALUES IN Maps
console.log( totalReplies.get(user1) ); // 5
console.log( totalReplies.get(user2) ); // 42
############################################################ 4.8
iterating maps with for...of loop
MAPS ARE ITERABLE, SO THEY CAN BE USED IN A for..of LOOP. EACH RUN FO THE LOOP RETURN
A [key,value] PAIR FOR AN ENTRY IN THE map.

EXAMPLE:
let mapSettings = new Map();
mapSettings.set( 'user', 'sam');
mapSettings.set( 'topic', 'ES2015');
mapSettings.set( 'replies', ['cant wait', 'so cool']);

for(let [key, value] of mapSettings){
	console.log(`${key} = ${value}`);
	
}
/*OUTPUT:
user = sam
topic = ES2015
replies = cant wait,so cool
*/

############################################################ 4.8
WEAKMAP: 6:19
THE WEAKMAP IS A TYPE OF MAP WHERE ONLY OBJECTS CAN BE PASSED AS KEYS, PRMITIVE DATA TYPES
-- SUCH AS STRING, NUMBERS, BOOLEANS, ETC, ARE NOT ALLOWED

EXAMPLE:
let user = {};
let comment = {};

let mapSettings = new WeakMap();
mapSettings.set( user, 'user');
mapSettings.set( comment, 'comment');

console.log( mapSettings.get(user));
console.log( mapSettings.get(comment));

mapSettings.set('title', 'es2015'); // invalid value used as weak map key
/*OUTPUT:
user
comment
*/
ERROR: Uncaught TypeError: Invalid value used as weak map key(…)

############################################################ 4.8
DIFFERENCE BETWEEKN A MAP VS WEAKMAP: 6:57
ALL AVAILABLE METHODS ON A WEAKMAP REQUIRE ACCESS TO AN OBJECT USED AS A KEY


let user = {};
let mapSettings = new WeakMap();
mapSettings.set(user, 'es2015');

console.log( mapSettings.get(user)); // get returns an entry
console.log( mapSettings.has(user)); // checks for the presence of a key, return true if there an entry for that key, or false if there is none
console.log( mapSettings.delete(user)); // deletes an entry and returns a boolean based on whether that entry existed
/*
OUTPUT:
es2015
true
 true
*/
// WEAKMAPS ARE NOT ITERABLE. THEREFORE, THEY CAN'T BE USED WITH FOR...OF LOOPS
for(let [key, value] of mapSettings){
	console.log(`${key} = ${value}`); // ERROR: script.js:16 Uncaught TypeError: mapSettings[Symbol.iterator] is not a function(…
	
}
############################################################ 4.8
QUESTION: SO WHY ARE WEAKMAPS USED.. 8:02
ANSWER: BECAUSE THEY ARE BETTER AT HOLDING MEMORY
WEAKMAPS ARE BETTER WITH MEMORY
INDIVIDUAL ENTIRES ON A WEAKMAP CAN BE GARBAAGE COLLECTED WHILE THE WEAKMAP ITSELF EXISTS
THEY HOLD A WEAK REFRENCE TO THE OBJECTS USED AS KEY - i have no idea what this bumbo jumbo means

FOR EXAMPLE:
let user = {}; // all objects occupy memory resource

let userStatus = new WeakMap();
userStatus.set( user, 'logged in'); // OBJECT REFERENCE PASSED AS KEY TO THE WEAKMAP
//... SOME CODE
someOtherFunction( user); // ONCE IT RETURN, USER CAN BE GARBAGE COLLECTED

//NOTE: WEAKMPAS DO NOT PREVEN THE GARBAGE COLLECTOR FROM COLLECTING OBJECTS CURRENTLY USE DAS KEYS, BUT THAT ARE NO LONGER FERENCED ANYWHER IN THE SYSTEM (OR THE DOM?)

############################################################ 4.17
SETS 0:10
THE SET OBJECT STORES UNIQUE VALUES OF ANY TYPE WHETHER PRIMITE VALUES OR OBJECT REFERENCES

IN ARRAYS, YOU CAN HAVE DUPLICATE ENTRIES
EXAMPLE:

let tags = [];
tags.push('javascript');
tags.push('javascript');
tags.push('PHP');
// EACH JAVASCRIPT IS COUNTED AS ONE, SO  A TOTAL OF 3 ITEMS ARE FOUND IN THE ARRAY
console.log('total items '+ tags.length ); // total items 3

############################################################ 4.17
SETS 0:57
USING SETS:

let tags = new Set();
// USE THE .add METHOD INSTEAD OF PUSH
tags.add('javascript');
tags.add('javascript'); // duplicate entries are ignored
tags.add({ version: '2016'}); // object value is allowed
tags.add('PHP'); // primitive value is allowed

console.log('total items '+ tags.size ); // total items 3

############################################################ 4.17
SETS ARE LOOPABLE (iterable) 1:50
set objects are iterable, which means they cna be used with for...of and destructring
let tags = new Set();
// USE THE .add METHOD INSTEAD OF PUSH
tags.add('javascript');
tags.add('javascript'); // duplicate entries are ignored
tags.add({ version: '2016'}); // object value is allowed
tags.add('PHP'); // primitive value is allowed
for(let tag of tags){
	console.log(tag); 
	
}
// NOTE THE DUPLICATES ARE ONLY SHOWN ONCE
/*
OUTPUT:
javascript
sObject {version: "2016"}
PHP
*/
############################################################ 4.17
WEAKSETS: 2:15
let weakTags = new WeakSet();

//// ERRRO WIL SAY:  Uncaught TypeError: Invalid value used in weak set(…)

weakTags.add( {name: 'Javascript'});
let iOS =  {name: 'IOS'};
weakTags.add(iOS);

//weakTags.has(iOS); // true (has checks for it has a value)
//weakTags.delete(iOS); // true

// NOTE:
// weaksets cannot be used with for..of loop and the dont give any method for reading values from it.
// if you try to run it on a for looop, you will get an error that says:

//example
for (let wt of weakTags) {
	console.log(wt); // ERROR: TypeError: weakTags is not iterable or CHROME: Uncaught TypeError: weakTags[Symbol.iterator] is not a function(…)
}
// when can you use weaksets? see 3:28

############################################################ 5.1
CLASSES: 0:15
THIS IS THE OLD WAY OF USING A FUNCTION APPROACH WHICH WAS A COMMON APPROACH
TO ENCAPSULATION IN JAVASCRIPT USING A CONSTRUCTOR FUNCTION
function SponsorWidget(name,description,url) {
	this.name		= name;
	this.description= description;
	this.url		= url;
}

SponsorWidget.prototype.render = function(){
	///..
}

// INVOKING THE SponsorWidget function looks like this:
let SponsorWidget = new SponsorWidget(name, description, url);
SponsorWidget.render(); //script.js:12 Uncaught SyntaxError: Identifier 'SponsorWidget' has already been declared

############################################################ 5.1
CLASSES: 2:15
NEW CLASS SYNTAX
using the new class syntax is easy. to define a class, you use the class keyword
followed by the name of the class then the body of the class goes betwween the curly braces
BASIC EXAMPLE:

class SponsorWidget{
	
	render(){ // instance method definition is classes look just like the method initialzer shortand in objects
	//..
	}
}
// what is a method is javascript, the method they call the code between the function
// the constructor method is a special method for creating and initializing an object.
############################################################ 5.1
CONSTRUCTOR METHOD: 3:00
class SponsorWidget{
	
	function SponsorWidget(name,description,url) {
	// RUNS EVERYTIME A NEW INSTANCE IS CREATED WITH THE NEW OPERATOR
	// ASSIGNING to instace variables makes them accessible by other instace methods
	this.name		= name;
	this.description= description;
	this.url		= url;	
	}

	ender(){

	}
}

// INVOKE THE SponsorWidget FUNCTION CLASS
// YOU CAN STILL USE THE SAME CODE AS BEFORE
let SponsorWidget = new SponsorWidget(name, description, url);
SponsorWidget.render(); 
############################################################ 5.1
CLASSES: 3:51
ACCESSING CLASS INSTANCE VARIABLES
instance variables set in the constructor method can be accessed from all other instance methods in the class

// THIS IS WHAT IS CALLED SYNTATIC SUGAR, ITS JUST A SIMPLER WAY TO WRITE THE SAME CODE
// the class syntax is not introducing a new object model to javascript, is only a syntactical sugar over an existing prototype-based inheritance.
EXAMPLE

class SponsorWidget{
	function SponsorWidget(name,description,url) {
	//..
	this.url = url; // DONT FORGET TO USE THIS TO ACCESS INSTACE PROPERTIES AND METHODS
	}

	ender(){
	let link = this._buildLink(this.url);
	//..
	}	

	// PREFIXING A METHOD WITH AN UNDERSCORE IS A CONVENTION FOR INDICATING THAT THIS FUNCTION SHOULD NOT
	// BE INVOKE FROM THE PUBLIC API
	// UNDERSCORE MEANS ITS A PRIVATE FUNCTION, SINCE JAVASCRIPT DOES NOT HAVE PUBLIC OR PRIVATE
	_buildLink(url){

		//..	
	}
}

############################################################ 5.1
INHERTIC CLASSES: 3:51

example:
class childClass extends ParentClass {
	

} 

class ParentClass{
	
}
############################################################ 5.7
MODULES 1:03
you can use modules to avoid naming the same variables from different javascript frameworks or libraries like jquery

!DOCTYPE html>
<html>
<head>
	<title></title>
	<script src="jquery.js"></script>
	<script src="bootstrap.js"></script>
	<script src="script.js"></script>
</head>

############################################################ 5.7
IMPORT  4:26

//flash-message.js
export function alertMessage(message){
		alert(message);
}
export function logMessage(message){
		console.log(message);
}
////////////////////////////////////////////////////////////
//flash-message.js - VERSION TWO, on this you can just use one 'export' in the file by putting it at the end of the file on the last line.
function alertMessage(message){
		alert(message);
}
function logMessage(message){
		console.log(message);
}
export {alertMessage,logMessage}
////////////////////////////////////////////////////////////
//app.js
// this import each function
import { alertMessage, logMessage} from './flash-message';

alertMessage("hello alert world")
logMessage("hello log world")
/////////////////////////////////////////////

//app.js VERSION 2
// this import each function
import  * as flash from './flash-message';

flash.alertMessage("hello alert world")
flash.logMessage("hello log world")
############################################################ 5.7
EXPORTING CONSTANTS: 2:03
// this is very helpful, by puting all your constants in a constants.js file so in the future
they change, you can just change them once.
/////////////////////// EXPORT /////////////
EXAMPLE 1:
//constants.js
export const MAX_USERS = 4;
export const MAX_REPLIES = 4;

EXAMPLE 2:
//constants.js
const MAX_USERS = 3;
const MAX_REPLIES = 4;
export{MAX_USERS,MAX_REPLIES};
/////////////////////// IMPORT /////////////
//load-profiles.js
import {MAX_USERS,MAX_REPLIES} from './constants.js';

function whatever(username){
		alert(MAX_USERS); //3
		alert(MAX_REPLIES); //4
}

############################################################ 5.13
EXPORTING CLASSES: 3:00

// flash-message.js
export default class FlashMessage{
	// since you are using the default class, you can assing any variable name
	// default allows this class to be set to any vairable name once its imported
	constructor(message){
		this.message  = message;
	}
	showAlert(){
		alert(this.message);
	}
	showLog(){
		console.log(this.message);
	}	
}

//app.js
// EXPORTING A CLASS, so F is capitalized
import FlashMessage from './flash-message.js'


// you MUST create a new instance fo FlashMessage using new
let flash = new FlashMessage('HI THERE');

// now you can call the functions in the FlashMessage class from flash-message.js
flash.showAlert();
flash.showLog();

############################################################ 6.1
PROMISES


############################################################ 6.5
ITERABLES
arrays are iterable objects, which means we can use them with fo..of loops
EXAMPLE
let names = ['sam','tyler','brook'];
for(let name of names){
	console.log( name);
}

// OBJECTS ARE NOT iterables with for. of loops
// SO THIS IS HOW YOU WOULD ITERATE AN OBJECT THROUGHT A FOR LOOP


############################################################ 6.5
ITERABLES
// THE OBJECT:
let post = {
	title: "New Features in JS",
	replies: 19
}

post[Symbol.iterator] = function(){
	let properties = Object.keys(this); // retuns an Array with property names
	let count = 0; // allow us to access the properties array by index
	let isDone = false; // will be set to true when we are done with the loop
	let next= () => {
		if(count >= properties.length){ // end the loop after reaching the last property
				isDone = true;
		}
		// this. refers to the post object
		// properties: fetches the value for the next property
		// count++ only increments count after it's read
		return { done: isDone, value:this[properties[count++]]}; 
	};

	return { next}; // iterator object
}

for(let p of post){
		console.log(p);
}
/*
OUTPUT:
New Features in JS
19
*/

// YOU CAN ALSO USE IT WITH THE SPREAD OPERATOR
console.log('##########USING SPREAD OPERATOR Returns an ARRAY: ###############');
let values = [...post];
console.log(values); // ["New Features in JS", 19]

// YOU CAN ALSO USE DESTRUCTURING
console.log('########## USING DESTRUCTURING ###############');
let [title,replies,] = post;
console.log(title); // New Features in JS
console.log(replies); //  19

############################################################ 6.5
GENERATORS
the function * declaration defines generator functions. these are special functions from which we can use the yield keywrod to return iterators objects.


// it doesnt matter where you put the star charactoer as long as it comes right after the function keyword
//examples:
// function *nameList(){
// function* nameList(){
// function * nameList(){

function *nameList(){
	// * is used
	// use the yield keyword to return iterators objects
	yield 'sam';  // { done: false, value: 'sam'}
	yield 'tyler'; // { done: false, value: 'tyler'}

}
for(let name of nameList()){
		console.log(name);
}
/*
OUTPUT:
sam
tyler
*/
// YOU CAN ALSO USE IT WITH THE SPREAD OPERATOR
console.log('##########USING SPREAD OPERATOR Returns an ARRAY: ###############');
let values = [...nameList()];
console.log(values); // ["sam", "tyler"]
// YOU CAN ALSO USE DESTRUCTURING
console.log('########## USING DESTRUCTURING ###############');
let [first,second,] = nameList();
console.log(first); // sam
console.log(second); //  tyler

############################################################ 6.9
YOU CAN CLEAN OUR CODE FROM secion 6.5

let post = {
	title: "New Features in JS",
	replies: 19
}

post[Symbol.iterator] = function * (){
	let properties = Object.keys(this); // retuns an Array with property names
	for(let p of properties){
			yield this[p];
	}

	/* WE DONT NEEX THIS CODE
	let count = 0; // allow us to access the properties array by index
	let isDone = false; // will be set to true when we are done with the loop
	let next= () => {
		if(count >= properties.length){ // end the loop after reaching the last property
				isDone = true;
		}
		// this. refers to the post object
		// properties: fetches the value for the next property
		// count++ only increments count after it's read
		return { done: isDone, value:this[properties[count++]]}; 
	};

	return { next}; // iterator object
	*/

}

for(let p of post){
		console.log(p);
}
/*
OUTPUT:
New Features in JS
19
*/

// YOU CAN ALSO USE IT WITH THE SPREAD OPERATOR
console.log('##########USING SPREAD OPERATOR Returns an ARRAY: ###############');
let values = [...post];
console.log(values); // ["New Features in JS", 19]

// YOU CAN ALSO USE DESTRUCTURING
console.log('########## USING DESTRUCTURING ###############');
let [title,replies,] = post;
console.log(title); // New Features in JS
console.log(replies); //  19