Instructor:
1
'c'
"str"
[1, 2, 3]
{ x: 1, text: "Hello", }
function(x,y) { return x+y; }
undefined
NaN
null
1 + 2
console.log ("Test")
;
return
return undefined
function f (x) { console.log ("Called with " + x); return x + 1;}
<input id="a" type="text" value="empty"/><div id="b"> <p>Hello</p></div><div id="c"> <p>World</p></div><script type="text/javascript" src="demo.js"></script>
function main () { var count = 0; var a = document.querySelector('input#a'); var b = document.querySelector('div#b'); var c = document.querySelector('div#c'); for (var x of [b,c]) { x.onclick = function (e) { e.target.outerHTML += "<p>Again! " + (count++) + "</p>"; } } a.value = 1 + 2; }document.addEventListener("DOMContentLoaded", main);
function f (x) { console.log ("1: " + x); console.log ("2: " + x.data); console.log ("3: " + x.data.length);}
> f ({ data: [11,21,31] });1: [object Object]2: 11,21,313: 3
> f ("pizza");1: pizza2: undefinedUncaught TypeError: Cannot read property 'length' of undefined
function f (x) { console.log ("1: " + (x / 2)); console.log ("2: " + (x[0]));}
> f ([11,21,31]);1: NaN2: 11
> f (8);1: 42: undefined
> f (undefined);1: NaNUncaught TypeError: Cannot read property '0' of undefined
{}
[]
[] + [] /* '' */[] + {} /* [object Object] */{} + [] /* VS8: 0, Node.js: [object Object] */{} + {} /* VS8: NaN, Node.js: [object Object][object Object] */
xs = ["10", "10", "10"];xs.map(parseInt) /* [10, NaN, 2] */[1,5,20,10].sort() /* [1, 10, 20, 5] */
Infinity
undefined + 1 /* NaN */false + 1 /* 1 (someone liked C) */5/0 /* Infinity */-1/0 /* -Infinity */
'' == '0'0 == ''0 == '0'10 == '10'9 == '9'10 > 9'10' > '9'1 + 91 + '9'1 + '9' == 19-1 + '11''11' - 1
false == 'false'false == ''false == '0'false == 0true == '1'true > false5/0 == 6/00/0 == 0/01/0 == -1/0/* floats suck (as usual) */1/10000000000000000000000 /* 1e-22 */1/100000000000000000000000 /* 1.0000000000000001e-23 */1/10000000000000000000000000 /* 9.999999999999999e-26 */1/1000000000000000000000000000 /* 1e-27 */false == undefinedfalse == nullnull == undefinedInfinity == InfinityNaN == NaN' \t\r\n ' == 0
'' == '0' /* false */0 == '' /* true */0 == '0' /* true */10 == '10' /* true */9 == '9' /* true */10 > 9 /* true */'10' > '9' /* false */1 + 9 /* 10 */1 + '9' /* '19' */1 + '9' == 19 /* true */-1 + '11' /* '-111' */'11' - 1 /* 10 */
false == 'false' /* false */false == '' /* true */false == '0' /* true */false == 0 /* true */true == '1' /* true */true > false /* true */5/0 == 6/0 /* true: x/0 is Infinity for x>0 */0/0 == 0/0 /* false: 0/0 is NaN */1/0 == -1/0 /* false: x/0 is -Infinity for x<0 *//* floats suck (as usual) */1/10000000000000000000000 /* 1e-22 */1/100000000000000000000000 /* 1.0000000000000001e-23 */1/10000000000000000000000000 /* 9.999999999999999e-26 */1/1000000000000000000000000000 /* 1e-27 */false == undefined /* false */false == null /* false */null == undefined /* true */Infinity == Infinity /* true */NaN == NaN /* false */' \t\r\n ' == 0 /* true */
Use ===, which does no conversions
===
Variables var are function-scoped
var
var a = 1;function f () { console.log ("f1: a = " + a); // a=undefined { var a = 2; console.log ("f2: a = " + a); // a=2 } }function main() { console.log ("m1: a = " + a); // a=1 f (); console.log ("m2: a = " + a); // a=1}
var a = 1;function f () { var a; /* = undefined */ console.log ("f1: a = " + a); // a=undefined { a = 2; console.log ("f2: a = " + a); // a=2 } }function main() { console.log ("m1: a = " + a); // a=1 f (); console.log ("m2: a = " + a); // a=1}
let
var a = 1;function f () { console.log ("f1: a = " + a); // a=1 { let a = 2; console.log ("f2: a = " + a); // a=2 } }function main() { console.log ("m1: a = " + a); // a=1 f (); console.log ("m2: a = " + a); // a=1}
var a = 1;function f (b) { a = 2; if (b) { var a; a = a + 1; } console.log (" f: a = " + a);}
function main() { f (true); console.log ("m1: a = " + a); f (false); console.log ("m2: a = " + a);}
f: a = 3m1: a = 1 f: a = 2m2: a = 1
Even when variable is already used "above" var declaration
function fib(n) { if (n==0) return 0; else if (n==1) return 1; else return fib(n-2) + fib(n-1);}
function fibtail(n) { // nested function, inner n shadows outer n function fibtail(n, r1, r2) { if (n===0) return r1; else if (n===1) return r2; else return fibtail(n-1, r2, r1+r2); } return fibtail(n, 0, 1);}
function swaparray(a) { let [x,y] = a; // deconstruct array a[0] = y; a[1] = x;}
Swap array
let a = [1, 2];swaparray(a);
Swap in place
let x = 1;let y = 2;[y,x] = [x,y];
=>
var xs = [ 11, 21, 31 ];xs.map (x => (2 * x));xs.filter (x => x%7===0);xs.reduce ((z,x) => z+x, 0);
var xs = [ 11, 21, 31 ];xs.map (function(x) { return (2 * x); });xs.filter (function(x) { return x%7===0 });xs.reduce (function(z,x) { return z+x; }, 0);
this
i
for (int i = 0; i < 5; i++) { int x = i; /* accepted: x effectively final */ new Thread (new Runnable () { public void run () { while (true) { System.out.print (x); } } }).start ();}
var funcs = [];for (var i = 0; i < 5; i++) { funcs.push (function () { return i; });}funcs.map (f => f());// [ 5, 5, 5, 5, 5 ]
Fix with var similar to Java?
var funcs = [];for (var i = 0; i < 5; i++) { var x = i; funcs.push (function () { return x; });}funcs.map (f => f());// [ 4, 4, 4, 4, 4 ]
Use block-scoped let
var funcs = [];for (var i = 0; i < 5; i++) { let x = i; /* block scope */ funcs.push (function () { return x; });}funcs.map (f => f());// [ 0, 1, 2, 3, 4 ]
Use let directly in for
for
var funcs = [];for (let i = 0; i < 5; i++) { funcs.push (function () { return i; });}funcs.map (f => f());// [ 0, 1, 2, 3, 4 ]
<div class="text-sm"> ```sh m1: a = 1 f1: a = undefined f2: a = 2 m2: a = 1 ``` <!-- </div>