link to notes https://git.io/vgpKc
- front-end web engineer
- funemployed, but joining Viki.com in a week
- recently spent 3 months in NYC at the Recurse Center
- retreat for programmers
- where people go to be better at what they do
- i learned a lot about vanilla JavaScript there
- i like making art with code
- subscribe to @piratefsh for tweets on tech, art and bad jokes.
- [email protected]
- i'm not here to bash JavaScript
- i actually
<3
it - but it's kinda quirky and easily misunderstood
- this is about what i wish i knew when i stared learning
- also, fun facts
- keep it conversational
- i will introduce a thing, and ask you things
- feel free to ask questions anytime
- we can discuss on the go
- for YOU to get as much understanding
- 30m - primer, types, equality, scope
- 10m - break, q&a
- 5m - hoisting
- 10m - the good parts, make friends with JavaScript
- end, q&a
- have you written JavaScript?
- dictionary check
- callbacks
- scope
- had flip table moments with JavaScript?
- JavaScript != Java
- back in era of Netscape Navigator (1990s)
- Netscape decided the web needed to be more dynamic
- a prototype was written by Brendan Eich in 10 days
- and was shipped with the next version of Netscape Navigator
- think about that the next time you ship hacky code
- ...but it has come a long way since
Let's talk about JavaScript types.
typeof 1 //=> number
typeof 'a' //=> string
typeof {} //=> object
typeof [] //=> ???
JavaScript has types, and they can be kinda unexpected.
undefined
is the default value assigned to a variable that hasn't been assigned one
var foo; // value is undefined
null
is used to explicitly say "there is no value here"
var person = {
name: 'Sher Minn',
opinionOnJustinBieber: null,
}
person.opinionOnJustinBieber //=> null
What ARE they, though?
typeof null //=> ???
typeof undefined //=> ???
Stands for 'Not a number'. Used in math operations when result is invalid
Math.sqrt(-1) //=> NaN
Well, guess what type it is?
typeof NaN //=> ???
Let's test for NaN...
NaN == NaN //=> ???
// undefined
typeof foo == 'undefined';
// NaN
isNaN(foo);
// null
foo === null;
What happens when you divide by zero in JavaScript?
2/0
In JavaScript, null
, undefined
and NaN
are all different things. treat them with respect.
So you think you know all about equivalence, right?
1 === 1
//=> true. same value.
1 === '1'
//=> false. different types.
var a = []
var b = []
a === b
//=> false, only true if is same object
a === a
//=> true, is same object
Allows you to compare values of different types. Pretty handy, right?
1 == 1
//=> true
1 == '1'
//=> true. the string gets converted into a number.
var a = []
var b = []
a == b
// => false
When comparing two values of same type (e.g. object), JavaScript secretly uses the '===' operator. Which is reasonable.
Type conversion only happens when values are of different types.
Then again, type conversion also gives us unexpected results...
var a = {}
var b = {}
a == b
// => false
a == '[object Object]'
// => true
b == '[object Object]'
// => true
Values of different types get converted into the same type before comparing.
For example, when comparing object
to string
, the object a
gets converted into a string before comparison. a.toString()
gives us "[object Object]"
which is equal to the string.
And then there's this.
What do you think this does?
var c;
if(!c){
console.log('c is undefined')
}
else{
console.log('c is damn fine');
}
But how about this?
if(c == false){
console.log('c is undefined')
}
else{
console.log('c is damn fine');
}
Guess what, !c
is not the same as c == false
(!!)
JavaScript converts our variable into a boolean (which is falsey), then applies the !
to reverse the value (to be truthy).
Whereas c == false
, does it's own special thing where it compares undefined
and false
and decides it's not the same thing (which is falsey).
not that you should be doing that in the first place.
undefined == null // rules of JavaScript say these are equal
null == undefined
=> true
undefined == true // expected, undefined isn't a true value
=> false
undefined == false // wait, but why?
=> false
Nothing equals to null
or undefined
except for null
and undefined
.
But both have 'falsey' values, i.e. if(undefined/null){}
will not execute.
!c
is not the same asc == false
.null
andundefined
have their own rules about truth and falsity- when comparing values of different types, values get converted to the same type, according to some rules (see further reading)
- just use strict equality already, geez
- Equality comparisons and sameness link - check out the table for comparisons to find out what conversions happen when comparing different types.
- Truthy and falsey - link
there are two types of scopes in JavaScript.
var hello = 2;
function hi(){
console.log(hello); //=> 2
}
function hi(){
var hi = 8;
}
console.log(hi); //=> undefined
what happens here?
function foo(){
if(true){
var x = 100;
}
console.log(x) //???
}
foo();
how about this?
function foo(){
function inner(){
var x = 100;
}
console.log(x) //???
}
foo();
objects have this special thing called this
which refers to that instance of an object.
here is an example where you might use it.
var me = {
name: 'Sher Minn',
sayName: function(){
console.log(this.name);
}
}
console.log(me.name); //=> Sher Minn
me.sayName(); //=> Sher Minn
sometimes, you might want to use this
in a callback.
var me = {
name: 'Sher Minn',
sayName: function(){
window.setTimeout(function(){
console.log(this.name);
}, 1000);
}
}
console.log(me.name); //=> Sher Minn
me.sayName(); //=> undefined, 'this' is the window object
My this.name
is undefined!
In JavaScript, the this
object will refer to the object that is calling the callback. Not the object where the callback is created, as you would expect.
In this case, the callback is created in the me
object, but called by window
in setTimeout
.
You can get JavaScript to use a specific this
.
var me = {
name: 'Sher Minn',
sayName: function(){
window.setTimeout(function(){
console.log(this.name);
}.bind(this), 1000);
}
}
console.log(me.name);
me.sayName(); //=> Sher Minn
this code
for(var i = 0; i < 4; i++){
setTimeout(function(){
console.log(i);
}, 100);
}
is expected to log 0 1 2 3
. but instead logs 4 4 4 4
.
why leh?
just try Googling 'callbacks in loops javascript'. so many articles and questions.
create new function for every call
for(var i = 0; i < 4; i++){
(function(ii){setTimeout(function(){
console.log(ii);
}, 100)})(i);;
}
function only created once and reused
function doThing(ii){
setTimeout(function(){
doThing(i);
}, 100);
}
for(var i = 0; i < 4; i++){
doThing(i);
}
create new function via bind. less efficient, but also less code.
for(var i = 0; i < 4; i++){
setTimeout(function(ii){
console.log(ii);
}.bind(null, i), 100);
}
- hey, y'alls, JavaScript is function scoped, not block scoped
- watch out for 'this' and variable references in a callback
freestyle chat. ask me about:
- Recurse Center
- generative art
- impostor syndrome
Suppose we try to use a non-existent variable
console.log(foobar); //=> ReferenceError: foobar is not defined
Suppose we try to use a variable BEFORE it was declared
console.log(foobar); //=> undefined. but the variable exists?
var foobar = 'hi peoples';
What really happens when var foobar = 'hi peoples'
is run?
- the
foobar
variable is declared foobar
is initialized the value'hi peoples'
var foobar = 'hi peoples';
is equivalent to
var foobar;
foobar = 'hi peoples';
Turns out JavaScript breaks it down to those two steps down. Then it does this thing called hoisting.
In action:
console.log(foobar);
var foobar = 'hi peoples';
is interpreted as:
var foobar; // variable DECLARATION hoisted
console.log(foobar);
foobar = 'hi peoples'; // variable initialization happens here
Back to the example I gave. This works:
foo(); //=> 'hi foo'
function foo(){
console.log('hi foo');
}
because JavaScript hoists the whole function to the top before it runs
// foo is hoisted up!
function foo(){
console.log('hi foo');
}
foo(); //=> 'hi foo'
And this doesn't...
foo(); // throws TypeError: foo is not a function
var foo = function(){
console.log('hi foo');
}
Because only the variable declaration is hoisted.
var foo;
foo(); // throws TypeError: foo is not a function (because foo is still undefined)
foo = function(){
console.log('hi foo');
}
var
andfunction
declarations get hoisted to the top before code is run- but values still get assigned at their original locations
How do you find the largest number in an array?
var arr = [4, 6, 9, 0, 1, 2];
Have you heard about Math.max()
?
Math.max(4, 6) //=> 6
It takes as many arguments as you want.
Math.max(4, 6, 9) //=> 9
But.. our numbers are in an array? Well...
Math.max(arr) //=> doesn't work. tries to sort the array as an element
In JavaScript though, you can do this (kinda like unpacking, if you're familiar with that):
Math.max.apply(null, arr) //=> ???
how would you iterate through an array?
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
you can do this the functional way. look at how nice and clean it is!
arr.forEach(function(elem){
console.log(elem);
}
also check these out as clean ways to manipulate arrays
map to perform an operation on each element
[1,2,3].map(function(elem){ return elem*elem }) // => [1, 4, 9]
reduce to 'reduce' an array in some way (e.g. total)
[1,2,3].reduce(function(total, elem){ return elem+total }, 0) // => 6
filter to filter out based on a condition
[1,2,3,4].filter(function(elem){return elem % 2 == 0; }) // => [2, 4]
- JavaScript can be hella sexy if you want it to be.
- JavaScript is just a misunderstood teenager everyone likes to poke fun at
- but actually, isn't that bad when you try to understand it
- beacase it's so weird, you get to dive really deep
- and turns out it's secretly cool
- it's hella dynamic
- does cool visual things in-browser
- JavaScript engines (such as V8 that runs in Chrome) are pretty efficient
- so, make JavaScript your friend
- write vanilla JavaScript
- frameworks are great, but they don't allow you to understand the basics
- i didn't have the chance to properly understand JavaScript during my JQuery/AngularJS days
- e.g. try implementing a tabs library in vanilla JavaScript
- you'd be surprised at how much you can do without JQuery.
- understanding things like these will make you a better programmer (i promise):
- scope
- closures
- hoisting
- prototype, classes, inheritance
- event callback loop
- call, bind, apply
- there are many ways to do one thing. pick one that makes sense to you and stick with it.
- use
'use strict'
mode. it will get your browser to check for potentially dangerous JavaScript code - use ES6 JavaScript, a newer spec of JavaScript that is a lot more standardized.
nice job, thank you sir, get a bird's eye view of your github profile summary here - https://alamnr.github.io/profile.html?user=piratefsh, it will be great if you review my js code of this project's repo (https://github.com/alamnr/alamnr.github.io/blob/master/js/new_git_promise.js) and suggest me for improvement - thanks.