Skip to content

Instantly share code, notes, and snippets.

@amgando
Last active July 21, 2019 20:19
Show Gist options
  • Save amgando/78284550f04cebe8efca to your computer and use it in GitHub Desktop.
Save amgando/78284550f04cebe8efca to your computer and use it in GitHub Desktop.
a quick intro the JS that focuses on functions
// to understand any system we must retain either control or visibility (or both)
// this is how you retain visibility
console.log('hello world')
// so now we can give up our need for control :)
// and along the way you'll see new words and language syntax. share your confusion!
// it's the greatest of gifts from a shameless heart and playfully curious mind.
// as a side note, sometimes when we learn something new, it's easier to go
// from lots of examples to a handful of rules, inductively, and sometimes
// it's better to go the other way, from a small set of rules to a boatload of
// examples, deductively.
// understanding javascript means understanding functions in javascript
// so let's start there, right at the heart of the matter.
// in javascript you can define a function. it's just a "named" piece of code
function a(){ console.log('hello from inside a function' )}
// ---------------------------------
// ---------------------------------
// functions can be invoked 4 different ways in javascript, each with different definitions of `this`
// (i think Ruby has only 3 of these but i'm always pleasantly surprised by that language)
// ---
// 1. direct invocation of the function
// (Ruby has this one, but the parens are optional unless passing args)
a() // the parens are necessary since 'a' just identifies the function
// ---
// 2. as part of an object, and here we call them 'methods'
// (Ruby has this one too, same as #1 re: parens)
o = {f:a}
o.f()
// ---
// 3. using call() or apply()
// (Ruby has this too and calls them 'lambdas' or 'procs')
a.call() // or a.apply(), but the difference is so small i'll ask you to wait for it
// ---
// 4. using the 'new' keyword
// (Ruby doesn't have this but the effects can be approximated by its module system)
b = new a // returns an empty object called 'a' and assigns it to 'b' (which we'll get to in a minute)
// ---------------------------------
// ok, that wasn't so bad. let's do it again, this time with gusto.
// but first, a digression. let's go back to Ruby.
// remember the keywork 'self' in Ruby?
// who feels like they've got a handle on that today?
// does anyone remember (or feel safe enough to admit) how hard it was to
// understand what the heck was going on with that word in the beginning? and
// can you feel how comfortable you are with it now? have you ever wondered
// why that is? why or when you become comfortable with that confusion?
// 2-year old: what's what? can i see it?
// parent: it's a calculator
// 2-year old: you mean calcuNOW!
// if you struggled, i suspect it's because of all the meaning you brought
// with you about the word "self".
// everytime you tried to wrap your head around the idea of "self", your mind got
// distracted by the word, it's sound, it's meaning and all the attachments you
// have to it. like yourself, myself, and our whole self.
// anyone heard of self the elf? me neither. moving on.
// let' say that every function gets 2 presents every time it's invoked:
// 'this' and 'arguments'
// except to help us make sense of things more quickly, i'm renaming those
// words just because i can, you know, because i'm controlling the keyboard
// right now.
// i'd like us to agree, for the next few minutes at least, to use the word
// 'teddy bear' instead of 'this' and 'box of chocolates' instead of 'arguments'.
// anyone bothered by these words? if you don't like them, choose your own,
// but do that later, ok? for now it's 'teddy' and the 'box' all the way down.
// so, back to work then, every function gets two sweet gifts when it's invoked:
// a teddy bear and a box of chocolates.
// let's take a close, experimental look at these things:
function a(){
console.log('hello from inside a function' ); // i'll just start ending lines
console.log('the teddy bear is: ', this); // with semicolons because it's the
console.log('the box of chocolates is: ', arguments); // the responsible thing to do
}
// and back to our 4 ways to invoke functions:
a(); // 1
o = {f:a};
o.f(); // 2
a.call(); // 3
b = new a; // 4
// ---
// hang on a second, that wasn't so exciting. let's spice it up a bit
a(1,2,3); // 1
o = {f:a};
o.f(1,2,3); // 2
a.call(1,2,3); // 3 (see refs below for explanation of ... Number {[[PrimitiveValue]]: 1}
b = new a(1,2,3); // 4
// ref: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
// ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
//
// ---
// as an aside here, we haven't added any parameters to the function
// signature. we can do that of course but it's good to know that Javascript
// doesn't enforce arity. function parameters are assigned just like in Ruby,
// if they're there. nothing special going on.
function b(x,y,z){ console.log(arguments); console.log(x, y, z) }
b();
b(1);
b(1,2);
b(1,2,3);
b(1,2,3,4);
// ---
// functions don't have implicit return types like in Ruby so unless you use
// the 'return' keyword you won't get anything back from the function.
// getting nothing back in Javascript means you're getting 'undefined', it's a
// more or less like Ruby's 'nil' but not exactly, that's actually 'null' in Javacript.
// undefined is more like "absence of value", distinctly different from a value of "null"
// and the debate rages on.
function c(){ 'hello' }
function d(){ return 'hello' }
function e(){ return null }
resultC = c(); // the value of resultC is undefined
resultD = d(); // the value of resultD is 'hello'
resultE = e(); // the value of resultD is null
// ref: https://developer.mozilla.org/en-US/docs/Glossary/null
// ref: https://developer.mozilla.org/en-US/docs/Glossary/undefined
// ---
// let's zoom in on 3 and 4.
// note: see the two refs above re: Primitive values wrapped in object constructors as opposed to literal values
// first #3
a.call(1,2,3); // with numbers
a.call('hello',2,3); // and a word
a.call(true,2,3); // and a boolean
a.call([],2,3); // and an array
a.call({},2,3); // and an empty object
// while we're at it, let's revisit the difference between call() and apply()
a.apply(1,[2,3]); // with numbers
a.apply('hello',[2,3]); // and a word
a.apply(true,[2,3]); // and a boolean
a.apply([],[2,3]); // and an array
a.apply({},[2,3]); // and an empty object
// and now #4, but let's modify the function a bit
function a(){
console.log('hello from inside a function' );
console.log('the teddy bear is: ', this);
console.log('the box of chocolates is: ', arguments);
this.x = arguments[0];
this.y = arguments[1];
}
b = new a(1,2,3); // 4
// in fact, #4 can be approximated using call() or apply() if we modify the function
function aa(){
console.log('hello from inside a function' );
console.log('the teddy bear is: ', this);
console.log('the box of chocolates is: ', arguments);
this.x = arguments[0];
this.y = arguments[1];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment