==================================== 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: Number String Boolean Symbol (new in edition 6) Object Function Array Date RegExp null undefined - 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] 3.14 2345.789 .333333333333333333 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, *** DO NOT TRUST FLOATING POINT NUMBERS WITH COMPARISON *** - 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. long\ line" 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: http://www.w3schools.com/jsref/jsref_obj_string.asp 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 text.search(pattern); // => 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: undefined null 0 -0 NaN "" // 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 References: 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: USECASE 1: var z=5; ( z == 5 ? function(){ console.log("A"); } : function(){ console.log("B"); } )(); USECASE 2: var fx = function(){ console.log("A"); } var fy = function(){ console.log("B"); } var z=5; ( z == 5 ? fx : fy })(); USECASE 3: (function(){ console.log("outer func"); (function(){ console.log("nested 1"); (function(){ console.log("nested 2"); (function(){ console.log("nested 3"); })(); })(); })(); })(); USECASE 4: var my = { funcs: [ function(p){ console.log("0000:" + p) ; return "p0"; }, function(p){ console.log("11111:"+p); 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