2021 年 11 月 22 日の週の生メモ


ENGLISH:

Gandolfo said this section is about how exactly functions execute.

She provided a diagram for the anatomy of a function.
I am familiar with the parts of the function, but one thing that I'm sometimes not cognizant of is that
*each parameter is simply a variable (a variable that has no value until the function is called)*.
Each argument (as opposed to a parameter) in the function call contains a value.

Remember that a function is a type of object, hence why we can put things like '.call' on a function.

One of the main purposes of "functional programming" is to minimize function "side effects".

On "side effects":
- She defines this way: Side effects are things that are happening, other than the value being returned,
that affect something outside of the function itself (outside of the curly braces of the function).
- I.e., a side effect is anything in a function that affects something outside of that function.
- E.g., 'console.log(...)' is a side effect because console.log() is logging to the console and the console exists outside of the function.
- Another e.g.: Changing the value of an object that's in a different scope.
- It's also the case that:
1) Manipulating the DOM is a side effect.
2) Manipulating the DOM often cannot be avoided in frontend web development.
- Robert: When you perform DOM manipulation, you change the state of the website/webapp,
and you are working with aspects of the program that live outside of your function.
So, DOM manipulation is a side effect because of the word 'manipulation',
and how the function you're writing is likely only taking arguments pertaining to the JavaScript,
but affecting your HTML as a 'side effect'.
- Robert: A pure function is one that has no side effects and returns the same data for the same arguments.



CODE:

// JS
// An important functionality difference between non-arrow functions and arrow functions:

// non-arrow function type 1
function experiment(a, b) {
  return arguments
}
console.log(experiment(2, 1)) // [2, 1]

// non-arrow function type 2
let experiment = function(a, b) {
  return arguments
}
console.log(experiment(2, 1)) // [2, 1]

// arrow function
let experiment = (a, b) => {
  return arguments
}
console.log(experiment(2, 1)) // Uncaught ReferenceError: arguments is not defined...

// The above error occurs with the arrow function because arrow functions don't have the 'arguments' array-like object.

// MDN: The 'arguments' object is a local variable available within all non-arrow functions. You can refer to a function's arguments inside that function by using its arguments object. It has entries for each argument the function was called with, with the first entry's index at 0.

// Another important functionality difference, between non-arrow and arrow functions, involves the 'this' keyword, just FYI.

//-------------------------------------------------------------------

// JS
// from the below array of objects, use 'filter' and 'map' to make an array of strings, where the strings are the names of the *present* suspects
const videoData = [
  {
    name: 'Miss Scarlet',
    present: true,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  },
  {
    name: 'Mrs. White',
    present: false,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  },
  {
    name: 'Reverend Green',
    present: true,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  },
  {
    name: 'Rusty',
    present: false,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  },
  {
    name: 'Colonel Mustard',
    present: true,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  },
  {
    name: 'Professor Plum',
    present: true,
    rooms: [
      {kitchen: false},
      {ballroom: false},
      {conservatory: false},
      {'dining room': false},
      {'billiard room': false},
      {library: false}
    ]
  }
]

const suspectObjPresent = videoData.filter(suspectObj => { return suspectObj.present })
const namesPresentSuspects = suspectObjPresent.map(suspectObj => { return suspectObj.name })
console.log(namesPresentSuspects) // ['Miss Scarlet', 'Reverend Green', 'Colonel Mustard', 'Professor Plum']

//-------------------------------------------------------------------

// JS
const createTuple = (a, b, c, d) => { // FYI a Tuple is a data structure that has a collection of arrays, each array with two values
  return [[a, c], [b, d]]
}
console.log(createTuple('It', 'be', 'could', 'anyone', 'no one')) // [['It', 'could'], ['be', 'anyone']]
// note that the 'no one' string wasn't picked up, so to speak

const createTuple = (a, b, c, ...d) => { // notice the 'spread operator', which "gathers all the extra *arguments* at the end and puts them in an array"
  return [[a, c], [b, d]]
}
console.log(createTuple('It', 'be', 'could', 'anyone', 'no one')) // [['It', 'could'], ['be', ['anyone', 'no one']]]

//-------------------------------------------------------------------

// JS
const createTuple = function(a, b, c, d) { // note that we've changed it to a non-arrow function because we want to be able to use 'arguments'
  console.log(arguments) // ['It', 'be', 'could', 'anyone', 'no one']
  return [[a, c], [b, d]]
}
console.log(createTuple('It', 'be', 'could', 'anyone', 'no one')) // [['It', 'could'], ['be', 'anyone']]

// just to be clear, 'console.log(arguments)' above logs: ['It', 'be', 'could', 'anyone', 'no one']
// so you can see that the 'arguments' keyword / array-like object *picks up the arguments that are passed into the function call*, no more, no less
// (the 'arguments' keyword has nothing to do with the 'spread operator')

//-------------------------------------------------------------------

// JS
// default parameters (an actual use case)
const add = function(a, b = 2) {
  console.log(arguments) // [3]
  return a + b
}
console.log(add(3)) // 5

// default parameters (just for learning)
const add = function(a = 2) {
  console.log(arguments) // []
  return a
}
console.log(add()) // 2

// default parameters (just for learning)
const add = function(a = 2) {
  console.log(arguments) // [3]
  return a
}
console.log(add(3)) // 3

//-------------------------------------------------------------------

// JS
// this is written in ES6
const add = function(a, b = 2) {
  console.log(arguments) // [3]
  return a + b
}
console.log(add(3)) // 5

// rewrite the above in ES5
const add = function(a, b) {
  b = b || 2 // i.e., b = b if b has value, and otherwise b = 2
  console.log(arguments) // [3]
  return a + b
}
console.log(add(3)) // 5

//-------------------------------------------------------------------

// JS
const constructArr = function() {
  console.log(arguments) // ['was', 'it', 'in'] (remember 'arguments' returns an array-like object, not an array, even though it looks similar when it's logged)
  const arr = Array.from(arguments) // this line takes 'arguments' and turns it into an array. Note 'Array.prototype.slice.call(arguments)' is the ES5 way
  console.log(arr) // ['was', 'it', 'in'] (now an actual array)
  arr.push('the billiards room?')
  console.log(arr) // ['was', 'it', 'in', 'the billiards room?']
  return arr.join(' ')
}
console.log(constructArr('was', 'it', 'in')) // was it in the billiards room?

// FYI an array-like object has numerical indices, like an array, and it has 'length' on it, like an array, but it doesn't have methods, like 'push()', on it