Last active
July 21, 2019 20:19
-
-
Save amgando/78284550f04cebe8efca to your computer and use it in GitHub Desktop.
a quick intro the JS that focuses on functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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