DEV Community

benboorstein
benboorstein

Posted on • Edited on

2 2

My Raw Notes for the Week of 12-13-2021

ENGLISH:

The purpose of these notes is to become acquainted with three methods: call(), apply(), and bind().

The difference between 'call()' and 'apply()':
- 'call()' takes arguments separately
- 'apply()' takes arguments as an array
Enter fullscreen mode Exit fullscreen mode
CODE:

// JS
// The Basics of JS Function Constructors aka Object Constructors (mostly from W3S)

function Person(first, last, age, eye) {
  this.firstName = first
  this.lastName = last
  this.age = age
  this.eyeColor = eye
}

const myFather = new Person('John', 'Doe', 50, 'blue') // myFather is storing what's called "a new instance of Person"

console.log(myFather) // Person {firstName: 'John', lastName: 'Doe', age: 50, eyeColor: 'blue'}

myFather.nationality = 'English'

console.log(myFather) // Person {firstName: 'John', lastName: 'Doe', age: 50, eyeColor: 'blue', nationality: 'English'}

myFather.fullName = function() {
  return `${this.firstName} ${this.lastName}`
}

console.log(myFather) // Person {firstName: 'John', lastName: 'Doe', age: 50, eyeColor: 'blue', nationality: 'English', fullName: ƒ ()}
console.log(myFather.fullName) // ƒ () { return `${this.firstName} ${this.lastName}` }
console.log(myFather.fullName()) // John Doe

// Note that we can't add a new property to a constructor the same way we add a new property to an existing object.
// In other words, the following does not work: Person.nationality = 'English'
// To add a new property to a constructor, we must add the new property to the actual constructor function.

// Just FYI:
// Built-in JS constructors for native objects
// new String()    // A new String object
// new Number()    // A new Number object
// new Boolean()   // A new Boolean object
// new Object()    // A new Object object
// new Array()     // A new Array object
// new RegExp()    // A new RegExp object
// new Function()  // A new Function object
// new Date()      // A new Date object

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

// JS
// call() (mostly from MDN)

// The 'call()' method calls a function with a given 'this' value and arguments provided *individually*.

// Example 1
// 'call()' provides a new value of 'this' to the function/method (the 'Food' function in the below example).
// With 'call()', we can write a method once (the 'Product' function in the below example) and then inherit it in another object,
// without having to rewrite the method for the new object.
function Product(productName, productPrice) {
  this.name = productName
  this.price = `$${productPrice}`
}

console.log(new Product('chocolate', 3)) // Product {name: 'chocolate', price: '$3'}

function Food(foodName, foodPrice) {
  Product.call(this, foodName, foodPrice)
  this.category = 'food'
}

console.log(new Food('cheese', 5)) // Food {name: 'cheese', price: '$5', category: 'food'}

console.log(new Food('cheese', 5).name) // cheese
console.log(new Food('cheese', 5).price) // $5
console.log(new Food('cheese', 5).category) // food


// Example 2
function Product(productName, productPrice, productWeight) {
  this.name = productName
  this.price = `$${productPrice}`
  this.weight = `${productWeight} lb.`
}

function Food(foodName, foodPrice, foodWeight) {
  Product.call(this, foodName, foodPrice, foodWeight)
  this.category = 'food'
}

console.log(new Food('cheese', 5, 2)) // Food {name: 'cheese', price: '$5', weight: '2 lb.', category: 'food'}


// Example 3
// We can use 'call()' to chain constructors for an object (similar to Java).
// In the following example, the constructor for the 'Product' object is defined with two parameters: 'productName' and 'productPrice'.
// Two other functions, 'Food' and 'Toy', *** invoke 'Product' ***, passing 'this', 'foodName'/'toyName', and 'foodPrice'/'toyPrice'.
// *** 'Product' initializes the properties 'name' and 'price'. ***
// Both specialized functions ('Food' and 'Toy') define the 'category'.
function Product(productName, productPrice) {
  this.name = productName
  this.price = `$${productPrice}`
}

function Food(foodName, foodPrice) {
  Product.call(this, foodName, foodPrice)
  this.category = 'food'
}

function Toy(toyName, toyPrice) {
  Product.call(this, toyName, toyPrice)
  this.category = 'toy'
}

const cheese = new Food('feta', 5)
const fun = new Toy('robot', 40)

console.log(cheese) // Food {name: 'feta', price: '$5', category: 'food'}
console.log(fun) // Toy {name: 'robot', price: '$40', category: 'toy'}


// Example 4
const person = {
  fullName: function() {
    return `${this.firstName} ${this.lastName}`
  }
}

const person1 = {
  firstName: 'John',
  lastName: 'Doe'
}

const person2 = {
  firstName: 'Jane',
  lastName: 'Doe'
}

console.log(person.fullName.call(person1)) // John Doe
console.log(person.fullName.call(person2)) // Jane Doe


// Example 5
const person = {
  fullName: function(city, country) {
    return `${this.firstName} ${this.lastName} is from ${city}, ${country}`
  }
}

const person1 = {
  firstName: 'John',
  lastName: 'Doe'
}

console.log(person.fullName.call(person1, 'Oslo', 'Norway')) // John Doe is from Oslo, Norway


// For other examples, like for using 'call()' to invoke an anonymous function, go here:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

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

// JS
// apply() (mostly from MDN)

// The 'apply()' method calls a function with a given 'this' value, and 'arguments' provided *as an array (or an array-like object)*.

// Example 1
const numbers = [5, 6, 2, 3, 7]
const max = Math.max.apply(null, numbers)
console.log(max) // 7
const min = Math.min.apply(null, numbers)
console.log(min) // 2

// Note that when the first argument of 'apply()' is 'undefined' or 'null', as in the above example,
// a similar outcome can be achieved using the array 'spread' syntax:
const numbers = [5, 6, 2, 3, 7]
const max = Math.max(...numbers)
console.log(max) // 7
const min = Math.min(...numbers)
console.log(min) // 2


// Example 2
// 'push()' appends the whole 'array2' array to 'array'.
// 'concat()' appends the elements from 'array2' to a new array.
// 'apply()' appends the elements from 'array2' to 'array'.

// With 'push()'
const array = ['a', 'b']
const array2 = [0, 1, 2]
array.push(array2)
console.log(array) // ['a', 'b', [0, 1, 2]]

// With 'concat()'
const array = ['a', 'b']
const array2 = [0, 1, 2]
const newArr = array.concat(array2)
console.log(newArr) // ['a', 'b', 0, 1, 2]

// With 'apply()'
const array = ['a', 'b']
const array2 = [0, 1, 2]
array.push.apply(array, array2)
console.log(array) // ['a', 'b', 0, 1, 2]


// Example 3
// Note that this example is identical to Example 4 of 'call()', but with 'apply()' instead.
const person = {
  fullName: function() {
    return `${this.firstName} ${this.lastName}`
  }
}

const person1 = {
  firstName: 'John',
  lastName: 'Doe'
}

const person2 = {
  firstName: 'Jane',
  lastName: 'Doe'
}

console.log(person.fullName.apply(person1)) // John Doe
console.log(person.fullName.apply(person2)) // Jane Doe


// Example 4
// Note that this example is identical to Example 5 of 'call()', except that:
// 'apply()' is used instead of 'call()' and 'apply()' accepts arguments in an *array*.

const person = {
  fullName: function(city, country) {
    return `${this.firstName} ${this.lastName} is from ${city}, ${country}`
  }
}

const person1 = {
  firstName: 'John',
  lastName: 'Doe'
}

console.log(person.fullName.apply(person1, ['Oslo', 'Norway'])) // John Doe is from Oslo, Norway


// For other examples, like for using 'apply()' to chain constructors for an object, go here:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

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

// JS
// bind() (mostly from MDN)

// The 'bind()' method creates a new function that, when called, has its 'this' keyword set to the provided value,
// with a given sequence of arguments preceding any provided when the new function is called.

// Example 1
// Creating a bound function
const module = {
  x: 42,
  getX: function() {
    return this.x
  }
}
console.log(module.getX()) // 42

const unboundGetX = module.getX
console.log(unboundGetX) // ƒ () { return this.x }
console.log(unboundGetX()) // undefined // the function gets invoked at the global scope

const boundGetX = unboundGetX.bind(module)
console.log(boundGetX()) // 42


// Example 2
// Creating a bound function, again
this.x = 9 // this 'this' refers to the global 'window' object

const module = {
  x: 81,
  getX: function() { return this.x }
}
console.log(module.getX()) // 81

const retrieveX = module.getX
console.log(retrieveX()) // 9 // the function gets invoked at the global scope

// Create a new function with 'this' bound to 'module'
const boundGetX = retrieveX.bind(module)
console.log(boundGetX()) // 81


// Example 3
// Partially applied functions (making a function with pre-specified initial arguments)
// These arguments (if any) follow the provided 'this' value and are then inserted at the start of the arguments
// passed to the target function, followed by whatever arguments are passed to the bound function at the time it
// is called.
function list() {
  return Array.from(arguments)
}

function addArguments(arg1, arg2) {
  return arg1 + arg2
}

const list1 = list(1, 2, 3)
console.log(list1) // [1, 2, 3]

const result1 = addArguments(1, 2)
console.log(result1) // 3

// Create a function with a preset leading argument
const leadingThirtysevenList = list.bind(null, 37)

// Create a function with a preset first argument.
const addThirtySeven = addArguments.bind(null, 37)

const list2 = leadingThirtysevenList()
console.log(list2) // [37]

const list3 = leadingThirtysevenList(1, 2, 3)
console.log(list3) // [37, 1, 2, 3]

const result2 = addThirtySeven(5)
console.log(result2) // 42 // from 37 + 5

const result3 = addThirtySeven(5, 10)
console.log(result3) // 42 // from 37 + 5 // the second argument is ignored


// For other examples, go here:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Enter fullscreen mode Exit fullscreen mode

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series