JavaScript study notes by Orhan Doğan

==================================== PART 1: CORE JAVASCRIPT ==================================== 

- Character Set: ECMAScript 5 requires implementations to support Unicode 3 or later.

- Case Sensitivity: JavaScript is a case-sensitive language. This means that language keywords, variables, function names, and other identifiers must always be typed with a consistent capitali- zation of letters. The while keyword, for example, must be typed “while,” not “While” or “WHILE.” Similarly, online, Online, OnLine, and ONLINE are four distinct variable names.

- Identifiers and Reserved Words: An identifier is simply a name. A JavaScript iden- tifier must begin with a letter, an underscore (_), or a dollar sign ($). Digits are not allowed as the first character so that JavaScript can easily distinguish identifiers from numbers. For portability and ease of editing, it is common to use only ASCII letters and digits in identifiers. Note, however, that JavaScript allows identifiers to contain letters and digits from the entire Unicode character set. Technically, the ECMAScript standard also allows Unicode characters from the obscure categories Mn, Mc, and Pc to appear in identifiers after the first character.

var sí = true; //valid :)
var π = 3.14; //valid :)
var $ = "hello"; //valid :)
var üşğçö="started with turkis letters.";  //totally valid :) Remember: JavaScript allows identifiers to contain letters and digits from the entire Unicode character set

- Reserved Words: JavaScript reserves a number of identifiers as the keywords of the language itself. You cannot use these words as identifiers in your programs

      break          delete         function        return		 typeof
      case           do	            if 		    switch		 var
      catch          else           in		    this		 void
      continue       false          instanceof	    throw		 while
      debugger       finally        new		    true		 with
      default        for            null            try		
      ECMAScript 5 reserves the following words:      
      class         const         enum            export      extends     import    super
      In addition, the following words, which are legal in ordinary JavaScript code, are re- served in strict mode:
      implements    let           private         public      yield     interface     package     protected     static

      Strict mode also imposes restrictions on the use of the following identifiers. They are not fully reserved, 
      but they are not allowed as variable, function, or parameter names:
      arguments   eval
      JavaScript predefines a number of global variables and functions, and you should avoid using their names
      for your own variables and functions:

      arguments           encodeURI             Infinity              Number              RegExp
      Array               encodeURIComponent    isFinite              Object              String
      Boolean             Error                 isNaN                 parseFloat          SyntaxError
      Date                eval                  JSON                  parseInt            TypeError
      decodeURI           EvalError             Math                  RangeError          undefined
      decodeURIComponent  Function              NaN                   ReferenceError      URIError
- Optional Semicolons: Like many programming languages, JavaScript uses the semicolon (;) to separate state- ment from each other. In JavaScript, you can usually omit the semicolon between two statements if those statements are written on separate lines. Many JavaScript programmers (and the code in this book) use semico- lons to explicitly mark the ends of statements, even where they are not required.

	var a = 3  //valid
	var b = 4  //valid

	a = 3; b = 4; //valid

	var a           //line 1
	a               //line 2
	=               //line 3
	3               //line 4
	console.log(a)  //line 5 :  this 5 lines equal to   var a; a=3; console.log(a);

These statement termination rules lead to some surprising cases. This code looks like two separate statements separated with a newline:
	var y = x + f    	//line 1
	(a+b).toString() 	//line 2:  this statement evalute like:  var y = x + f(a+b).toString()  :::  
				// this is not the interpretation intended by the author of the code.

There are two exceptions to the general rule that JavaScript interprets line breaks as semicolons when it cannot parse the second line as a continuation of the statement on the first line. The first exception involves the return, break, and continue statements.

return //line 1
true;  //line 2
//above lines: JavaScript assumes you meant: "return; true;"   However, you probably meant: "return true;"

- Types, Variables, Values:
      Symbol (new in edition 6)

- Numbers: Unlike many languages, JavaScript does not make a distinction between integer values and floating-point values. All numbers in JavaScript are represented as floating-point values. JavaScript represents numbers using the 64-bit floating-point format defined by the IEEE 754 standard,1 which means it can represent numbers as large as ±1.7976931348623157 × 10308 and as small as ±5 × 10−324.

- Integer Literals: 
  base-10 : //1234
  base-16 : // 0xff
  base-8  : // 0377   // 3*64 + 7*8 + 7 = 255 (base 10) :::  you should never write an integer literal with a leading zero; you cannot know in this case whether an implementation will interpret it as an octal or decimal value. In the strict mode of ECMAScript 5 (§5.7.3), octal literals are explicitly forbidden.

- Floating-Point Literals: [digits][.digits][(E|e)[(+|-)]digits]
      6.02e5 // 6.02 x 100000 =>602000
      1.4733E-3 // 1.4738223 x (1/1000) =>   0,0014733
- Arithmetic in JavaScript:      
        Math.pow(2,53)          // => 9007199254740992: 2 to the power 53
	Math.round(.6)          // => 1.0: round to the nearest integer
	Math.ceil(.6)           // => 1.0: round up to an integer
	Math.floor(.6)          // => 0.0: round down to an integer      
	Math.abs(-5)            // => 5: absolute value
	Math.max(x,y,z)         // Return the largest argument
	Math.min(x,y,z)         // Return the smallest argument
	Math.random()           // Pseudo-random number x where 0 <= x < 1.0
	Math.PI                 // π: circumference of a circle / diameter
	Math.E                  // e: The base of the natural logarithm
	Math.sqrt(3)            // the square root of 3
	Math.pow(3, 1/3)        // The cube root of 3
	Math.sin(0)             // Trigonometry: also Math.cos, Math.atan, etc.
	Math.log(10)            // Natural logarithm of 10
	Math.log(100)/Math.LN10 // Base 10 logarithm of 100
	Math.log(512)/Math.LN2  // Base 2 logarithm of 512
	Math.exp(3)             // Math.E cubed
	Arithmetic in JavaScript does not raise errors in cases of overflow, underflow, or divi- sion by zero. When the result of a numeric operation is larger than the largest repre- sentable number (overflow), the result is a special infinity value, which JavaScript prints as Infinity. Similarly, when a negative value becomes larger than the largest repre- sentable negative number, the result is negative infinity, printed as -Infinity.
	1/0 			// => Infinity
       -1/0			// => -Infinity
        0/0			// => NaN   Not a Number
	Math.sqrt(-number)	// => NaN 
	Infinity/Infinity	// => NaN
The not-a-number value has one unusual feature in JavaScript: it does not compare equal to any other value, including itself. This means that you can’t write x == NaN to determine whether the value of a variable x is NaN. Instead, you should write x != x.

	NaN == NaN		// => false :) yes truely, false :)
	isNaN()			// if the parameter, argument is NaN, or a non-numeric value such as a string or an object.
	var x=NaN; x!=x; 	// => true :) because NaN == NaN => false

Look at below 3 lines for NaN:
	var x = 0/0;		// => x=NaN
	var y = x != x;		// => y=true beacause it is a way to understand if a variable is NaN. or use isNAN()
	var z = isNaN(x)	// => z = true

Checking is number of not:
	isFinite(value); 	// The isFinite() function determines whether a number is a finite, legal number.
	isFinite(123);		// => true
	isFinite("123");	// => true	
	isFinite("123a");	// => false
	isFinite("0x123a");	// => true :)  because  hexadecimal represantation
	isFinite("0x123aH");	// => false :)  it seams like hexadecimal but no "H"! :)
	isFinite("123    ");	// => true :)  white spaces, even cariage returns ommited if there is noanyletter at the end

- Binary Floating-Point and Rounding Errors:

	Because of rounding error, the difference between the approximations of .3 and .2 is not exactly the same 
	as the difference between the approximations of .2 and .1. It is important to understand that this problem 
	is not specific to JavaScript: it affects any programming language that uses binary floating-point numbers. 
	Also, note that the values x and y in the code above are very close to each other and to the correct value. 
	The computed values are adequate for almost any purpose: the problem arises when we attempt to compare 
	values for equality.

	var x= 0.3 - 0.2;		// => 0.09999999999999998   (17 digit after dot.)
	var y= 0.2 - 0.1;		// => 0.1

	console.log(x == y);		// => false
	console.log(x == 0.1);		// => false
	console.log(x == 0.1);		// => false
	console.log( Math.round(x*1e9) == Math.round(y*1e9));	// => true, 

- Dates and Times:
	Core JavaScript includes a Date() constructor for creating objects that represent dates and times.
	var then = new Date(2016,0,1);				// => Fri Jan 01 2016 00:00:00 GMT+0200 (EET)
	var later = new Date(2016, 11, 31, 15, 30, 45);		// => Sat Dec 31 2016 15:30:45 GMT+0200 (EET)
	var now = new Date();					// The current date and time
	var elapsed = now - then;				// Date subtraction: interval in milliseconds
	later.getFullYear();					// => 2016
	later.getMonth();					// => 11: zero-based months
	later.getDate();					// => 31: one-based days
	later.getDay();						// => 6: day of week. 0 is Sunday 6 is Saturday.
	later.getHours();					// => 15: 3pm, local time
	later.getUTCHours();					// hours in UTC time; depends on timezone
	later.toString();					// => "Sat Dec 31 2016 15:30:45 GMT+0200 (EET)"
	later.toUTCString();					// => "Sat, 31 Dec 2016 13:30:45 GMT"
	later.toLocaleDateString();				// => "12/31/2016"
	later.toLocaleTimeString();				// => "3:30:45 PM"
	later.toISOString();					// => "2016-12-31T13:30:45.000Z"
- String Literals:
	A string is an immutable ordered sequence of 16-bit values, each of which typically represents a Unicode 
	character—strings are JavaScript’s type for representing text. 
	In ECMAScript 3, string literals must be written on a single line. In ECMAScript 5, however, you can break 
	a string literal across multiple lines by ending each line but the last with a backslash (\).
	"two\nlines" // A string representing 2 lines written on one line
	"one\ // A one-line string written on 3 lines. ECMAScript 5 only.
	var msg = "Hello, " + "world"; // Produces the string "Hello, world" 
	var greeting = "Welcome to my blog," + " " + name;

	*** All string methods return a new value. They do not change the original variable. ***
	Check String methods at:
	String Properties:
	length				Returns the length of a string
	prototype			Allows you to add properties and methods to an object

	String Methods:			Not: each method start witha string:  "hello".charAt(0) ==> h
	charAt(index)			Returns the character at the specified index (position)
	charCodeAt(index)		Returns the Unicode of the character at the specified index
	concat(str1, str2, .., strN)	Joins two or more strings, and returns a new joined strings
	endsWith(searchvalue,length)	Checks whether a string ends with specified string/characters. (only ECMAScript 6)
	fromCharCode(n1, n2, ..., nX)	Converts Unicode values to characters
	includes(searchvalue,start)	Checks whether a string contains the specified string/characters
	indexOf(searchvalue,start)	Returns the position of the first found occurrence of a specified value in a string
	lastIndexOf(searchvalue,start)	Returns the position of the last found occurrence of a specified value in a string
	localeCompare()			Compares two strings in the current locale
	match()				Searches a string for a match against a regular expression, and returns the matches
	repeat()			Returns a new string with a specified number of copies of an existing string
	replace()			Searches a string for a specified value, or a regular expression, and 
					returns a new string where the specified values are replaced
	search()			Searches a string for a specified value, or regular expression, 
					and returns the position of the match
	slice()				Extracts a part of a string and returns a new string
	split()				Splits a string into an array of substrings
	startsWith()			Checks whether a string begins with specified characters
	substr()			Extracts the characters from a string, beginning at a specified start position, 
					and through the specified number of character
	substring()			Extracts the characters from a string, between two specified indices
	toLocaleLowerCase()		Converts a string to lowercase letters, according to the host's locale
	toLocaleUpperCase()		Converts a string to uppercase letters, according to the host's locale
	toLowerCase()			Converts a string to lowercase letters
	toString()			Returns the value of a String object
	toUpperCase()			Converts a string to uppercase letters
	trim()				Removes whitespace from both ends of a string
	valueOf()			Returns the primitive value of a String object	
Pattern Matching:
	JavaScript adopts Perl’s syntax for regular expressions. Both strings and RegExp objects have methods 
	for performing pattern matching and search-and-replace operations using regular expressions.

	/^HTML/				// Match the letters H T M L at the start of a string
	/[1-9][0-9]*/			// Match a non-zero digit, followed by any # of digits
	/\bjavascript\b/i		// Match "javascript" as a word, case-insensitive
	var text = "testing: 1, 2, 3"; 	// Sample text
	var pattern = /\d+/g;		//  Matches all instances of one or more digits
	pattern.test(text);		// => true: a match exists;		// => 9: position of first match
	text.match(pattern);		// => ["1", "2", "3"]: array of all matches
	text.replace(pattern, "#"); 	// => "testing: #, #, #"
	text.split(/\D+/); // => ["","1","2","3"]: split on non-digits
Boolean Values:
	The following values convert to, and therefore work like, false:
	"" // the empty string
	all other values like, true:
	"1"  // true
	"0"  // true  in php => false

Wrapper Objects:
	Strings, numbers, and boolean values behave like objects when you try to read the value of a property 
	(or method) from them. But if you attempt to set the value of a property, that attempt is silently 
	ignored: the change is made on a temporary object and does not persist. You just need to know that 
	string, number, and boolean values differ from objects in that their properties are read-only and 
	that you can’t define new properties on them.
	var s = "test";			// start with a string value
	s.tcolor = "red";		// set a property on it
	var t = s.tcolor;		// try to read that property and assing to a new variable.
					// at 3th line, s.tcolor is undefined. 
Immutable Primitive Values and Mutable Object
	There is a fundamental difference in JavaScript between primitive values (undefined, null, booleans, 
	numbers, and strings) and objects (including arrays and functions). Primitives are immutable: 
	*** there is no way to change (or “mutate”) a primitive value. ***
	*** Primitives are compared by value ***
	*** Objects are not compared by value: two objects are not equal even if they have the same properties and values.***
	***  And two arrays are not equal even if they have the same elements in the same order ***
	Objects are sometimes called reference types to distinguish them from JavaScript’s primitive types. 
	Using this terminology, object values are references, and we say that objects are compared by reference: 
	two object values are the same if and only if they refer to the same underlying object. (Page 63) it does not 
	create a new copy of the object. If you want to make a new copy of an object or array, you must explicitly 
	copy the properties of the object or the elements of the array. 
	var a = ['a','b','c']; 			// An array we want to copy
	var b = []; 				// A distinct array we'll copy into 
	for(var i = 0; i < a.length; i++) { 	// For each index of a[]
		b[i] = a[i];			// Copy an element of a into b 
	Similarly, if we want to compare two distinct objects or arrays, we must compare their properties or elements.

	function equalArrays(a,b) {				// Different-size arrays not equal
		if (a.length != b.length) return false;		// Loop through all elements
		for(var i = 0; i < a.length; i++)		// If any differ, arrays not equal
			if (a[i] !== b[i]) return false;	// Otherwise they are equal
		return true;
Explicit Conversions:
	The simplest way to perform an explicit type conversion is to use the Boolean(), Number(), String(), 
	or Object() functions. We’ve already seen these functions as con- structors for wrapper objects. 
	When invoked without the new operator, how- ever, they work as conversion functions and perform 
	the conversions summarized in Table 3-2:
	Number("3") 		// => 3
	String(false) 		// => "false" Or use false.toString()
	Boolean([]) 		// => true
	Object(3)		// => new Number(3)

	Note that any value other than null or undefined has a toString() method and the result of this 
	method is usually the same as that returned by the String() function.
	The toString() method defined by the Number class accepts an optional argument that specifies 
	a radix, or base, for the conversion.
	var n = 17;				
	binary_string = n.toString(2); 		// Evaluates to "10001"
	octal_string = "0" + n.toString(8); 	// Evaluates to "021"
	hex_string = "0x" + n.toString(16);	// Evaluates to "0x11"
	When working with financial or scientific data, you may want to convert numbers to strings in ways 
	that give you control over the number of decimal places or the number of significant digits 
	in the output, or you may want to control whether exponential notation is used. The Number class 
	defines three methods for these kinds of number- to-string conversions. toFixed() converts a number 
	to a string with a specified number of digits after the decimal point.	
	var n = 123456.789; 
	n.toFixed(0); 		// "123457"
	n.toFixed(2); 		// "123456.79"
	n.toFixed(5); 		// "123456.78900"
	n.toExponential(1); 	// "1.2e+5"
	n.toExponential(3); 	// "1.235e+5"
	n.toPrecision(4); 	// "1.235e+5"
	n.toPrecision(7); 	// "123456.8"
	n.toPrecision(10);	// "123456.7890"

	Both parseInt() and parseFloat() skip leading white- space, parse as many numeric characters as they can, 
	and ignore anything that follows. If the first nonspace character is not part of a valid numeric literal, 
	they return NaN:
	parseInt("3 blind mice") 		// 3
	parseFloat(" 3.14 meters") 		// 3.14
	parseInt("-12.34") 			// -12
	parseInt("0xFF") 			// 255
	parseInt("0xff") 			// 255
	parseInt("-0XFF") 			// -255
	parseFloat(".1") 			// 0.1
	parseInt("0.1") 			// 0
	parseInt(".1") 				//  NaN: integers can't start with "."
	parseFloat("$72.47");			// NaN: numbers can't start with "$"
	parseInt() accepts an optional second argument specifying the radix (base) of the number to be parsed. 
	Legal values are between 2 and 36. For example:
	parseInt("11", 2); 		// 3 (1*2 + 1)
	parseInt("ff", 16); 		// 255 (15*16 + 15)
	parseInt("zz", 36); 		// 1295 (35*36 + 35)
	parseInt("077", 8); 		// 63 (7*8 + 7)
	parseInt("077", 10);		// 77 (7*10 + 7)
Variable Declaration:
	Before you use a variable in a JavaScript program, you should declare it. Variables are declared
	with the var keyword, like this:

	var i; 
	var sum;

	You can also declare multiple variables with the same var keyword: 
	var i, sum;

	And you can combine variable declaration with variable initialization:

	var message = "hello"; 
	var i = 0, j = 0, k = 0;
	If you don’t specify an initial value for a variable with the var statement, the variable is declared,
	but its value is undefined until your code stores a value into it.
	It is legal and harmless to declare a variable more than once with the var statement. If the repeated 
	declaration has an initializer, it acts as if it were simply an assignment statement.

Variable Scope: 
	Within the body of a function, a local variable takes precedence over a global variable with the same name. 
	If you declare a local variable or function parameter with the same name as a global variable, you effectively 
	hide the global variable:
	var scope = "global"; 			// Declare a global variable
	function checkscope() {
		var scope = "local"; 		// Declare a local variable with the same name
		return scope;			// Return the local value, not the global one
	checkscope();				// => "local"
Nested Function Definitions and Scope:	
	Function definitions can be nested. Each function has its own local scope, so it is pos- sible to have 
	several nested layers of local scope. For example:	
	var scope = "global scope"; 				// A global variable
	function checkscope() {
		var scope = "local scope"; 			// A local variable
		function nested() {
			var scope = "nested scope"; 		// A nested scope of local variables
			return scope;				// Return the value in scope here
		return [scope,nested()]; 
	console.log([scope, checkscope()]);			// => Array[2]
								//	0:"global scope"
								//	1:Array[2]
								//		0:"local scope"
								//		1:"nested scope"

Function Scope and Hoisting:
	In some C-like programming languages, each block of code within curly braces has its own scope, and 
	variables are not visible outside of the block in which they are declared. This is called block scope, 
	and JavaScript does not have it. Instead, JavaScript uses function scope: variables are visible within 
	the function in which they are defined and within any functions that are nested within that function.
	JavaScript’s function scope means that all variables declared within a function are visi- ble throughout 
	the body of the function. 

	var scope = "global"; 
	function f() {
		console.log(scope); 	// Prints "undefined", not "global"
		var scope = "local"; 	// Variable initialized here, but defined everywhere 
		console.log(scope); 	// Prints "local"

Shortghand Function Definitions:

	var z=5; ( z == 5 ? function(){ console.log("A"); } : function(){ console.log("B"); }  )();
	var fx = function(){ console.log("A"); }
	var fy = function(){ console.log("B"); }
	var z=5; ( z == 5 ? fx : fy })();
		console.log("outer func"); 
			console.log("nested 1"); 
				console.log("nested 2"); 
					console.log("nested 3"); 

	var my = { funcs: [
				console.log("0000:" + p) ;
				return "p0";
				return "p1";

	console.log(typeof (my.funcs[1] || function(){return false})("ok") ); 	// => 11111:ok  
										// => string
	console.log(typeof (my.funcs[5] || function(){return false})("ok") );	// => boolean
	console.log(typeof my.funcs[0]("ok"));					// => 0000:ok
										// => string