### Topics * Operators * var , let and const * The __this__ * Fat arrow * Templete literal * Destructor --- ### JavaScript Bad Parts - 1 * Operator * Choose `== or ===` * Choose `!= or !==` --- * Test yourself ```js console.log( " 1==true : ", 1==true) console.log( " ''==true : ", ''==true) console.log( " '1'==true : ", '1'==true) console.log( " \"1\"==true : ", "1"==true) console.log( " {}==true : ", [{}]==true) console.log( " []==true : ", ['1']==true) ``` --- ```js console.log("1==true : ", 1==true) // 1==true : true console.log("''==true : ", ''==true) // ''==true : false console.log("'1'==true : ", '1'==true) // '1'==true : true console.log("\"1\"==true : ", "1"==true)// "1"==true : true console.log("{}==true : ", {}==true) // {}==true : false console.log("['1']==true : ", ['1']==true) // []==true : true ``` --- * Test yourself ```js console.log( " 0==false : ", 0==false) console.log( " 1==false : ", 1==false) console.log( " ''==false : ", ''==false) console.log( " '1'==false : ", '1'==false) console.log( " \"\"==false : ", ""==false) console.log( " {}==false : ", {}==false) console.log( " []==false : ", []==false) console.log( " ['0']==false : ", ['0']==false) ``` --- ```js console.log( " 0==false : ", 0==false) // 0==false : true console.log( " 1==false : ", 1==false) // 1==false : false console.log( " ''==false : ", ''==false) // ''==false : true console.log( " '1'==false : ", '1'==false)// '1'==false : false console.log( " \"\"==false : ", ""==false)// ""==false : true console.log( " {}==false : ", {}==false) // {}==false : false console.log( " []==false : ", []==false) // []==false : true console.log( " ['0']==false : ", ['0']==false) // []==false : true ``` --- * Test yourself ```js console.log( " null==false : ", null==false) console.log( " undefined==false : ", undefined==false) console.log( " undefined==null : ", null==undefined) ``` --- ```js console.log( " null==false : ", null==false) // null==false: false console.log( " undefined==false : ", undefined==false) // undefined==false: false console.log( " undefined==null : ", null==undefined) // undefined==null: true ``` --- * JavaScript has both strict and type–converting comparisons. A strict comparison (e.g., ===) is only true if the operands are of the same type and the contents match. The more commonly-used abstract comparison (e.g. ==) converts the operands to the same type before making the comparison. --- ### Quiz Compare two arrays of number are the same --- ### JavaScript Bad Parts - 2 ## The **var** --- * Test yourself ```js function testVar(){ console.log(a) console.log(b) var b = 2 } var a = 1 testVar() console.log(b) ``` --- * Test yourself (Browser) - TBC ```js d = 13 console.log(this.d) delete this.d console.log(this.d) var e = 31 console.log(this.e) delete this.e console.log(this.e) var i = i + 1 console.log( i ) console.log( this.i ) ``` --- ```js var e = 31 f = 13 console.log(this.e, this.f) // 31 13 console.log(e, f) // 31 13 delete this.f delete this.e console.log(this.e, this.f) // 31 undefinded console.log(e, f) // ReferenceError: d is not defined var i = i + 1 console.log( i ) // NaN console.log( this.i ) // NaN ``` --- Conclusion: Because of the above unexpected results, it is recommended to always declare variables, regardless of whether they are in a function or global scope. --- * Test yourself ```js var var1; let letVar; const constVar; function testVar() { console.log( var1); console.log( constVar); console.log( letVar); } ``` --- ```js var var1; let letVar; const constVar; // missing initialization function testVar() { console.log( var1); console.log( constVar); console.log( letVar); } ``` --- * Test yourself ```js var v1 = ""; var v1 = 123; let let1 = ""; let let1 = 123; const c1 = ""; c1 = 123; ``` --- ```js var v1 = ""; var v1 = 123; let let1 = ""; let let1 = 123; //SyntaxError: Identifier 'let1' has already been declared. const c1 = ""; c1 = 123; // TypeError: Assignment to constant variable. ``` --- * Test yourself ```js for ( var i = 0 ; i < 5 ; i++ ){ var x = 20; console.log(i); } console.log( i ); console.log( x ); for ( ; i < 10 ; i++ ){ var i console.log(i); } ``` --- ```js for ( var i = 0 ; i < 5 ; i++ ) { var x = 20 console.log(i);//0 1 2 3 4 } console.log(i);//5 console.log(x);//20 for ( ; i < 10 ; i++ ){ var i// re-declare will not reset value console.log(i);//5 6 7 8 9 } ``` --- * Test yourself ```js for ( let t = 0 ; t < 5 ; t++ ){ console.log( t); let s = 100 } console.log(s) console.log(t) ``` --- ```js for ( let t = 0 ; t < 5 ; t++ ){ console.log( t); let s = 100 } console.log(t)//ReferenceError: t is not defined console.log(s)// ``` --- * let allows you to declare variables that are limited to a scope of a block statement, or expression on which it is used, unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope. The other difference between var and let is that the latter is initialized to value only when parser evaluates it --- * Constants are block-scoped, much like variables defined using the let statement. The value of a constant can’t be changed through reassignment, and it can’t be re-declared. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. --- ### JavaScript Bad Parts - 3 ## The unpredictable **this** keyword [MDN] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) In most cases, the value of this is determined by how a function is called (runtime binding). It can't be set by assignment during execution, and it may be different each time the function is called. --- * Test ```js var obj0 = { prop: 'obj0', func_1: function () { console.log(' func_1-> ', this); var func_2 = { prop: 'func_2', func_3: function () { console.log(' func_3 -> ', this); } }; func_2.func_3(); } }; obj0.func_1(); ``` --- * Test ```js var obj1 = { prop: 'obj1', func_1: function () { console.log(' func_1-> ', this); func_2 = function () { this.prop = 'func_2'; var func_3 = function () { this.p = 'func_3'; console.log(' func_3 -> ', this); } return func_3 }; func_2()(); } }; obj1.func_1(); ``` --- * Test (Fat Arrow) ```js var obj2 = { prop: 123, func_1: () => { console.log(' func_1-> ', this); func_2 = { prop: 'func_2', func_3: () => { this.p = 'func_3'; console.log(' func_3 -> ', this); } }; func_2.func_3(); } }; obj2.func_1(); ``` --- * Test ( Binding ) ```js var obj3 = { p: 'obj3', toBeCalled: function () { console.log(' this is toBeCalled ', this.p); }, toBind: function (obj) { obj.toBeCalled(); } }; var testBind = obj3.toBind; testBind(obj3); var obj4 = { p: 'obj4', toBeCalled: () => { console.log(' this is toBeCalled ', this.p); }, toBind: obj => { obj.toBeCalled(); } }; var testBind2 = obj4.toBind; testBind2(obj4); ``` --- ### Arrow Function An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords. Arrow function expressions are ill suited as methods, and they cannot be used as constructors. --- ```js const arrFunc = p1 => p2 => console.log(p1," ",p2) arrFunc("Hello")("World") const arrFunc2 = p1 => { return p2 => console.log(p1," ",p2) } arrFunc2("Hello")("World") ``` --- ### Template literal Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them. --- ```js // literal const message = ` hello developer ${1+1} ${new Date()} ` console.log( message) ``` --- ### Destructor ```js const person = { name: "name", fullName: "full name", email: "email@test.com" } const testDestructor = (p) => { const { name, fullName , email } = {...p}; console.log(` name: ${name} fullName: ${fullName} email: ${email} ${new Date()} `) } testDestructor( person ) ``` ---