DEV Community

Mitchell
Mitchell

Posted on • Edited on

Function prototype - JavaScript Challenges

You can find all the code in this post in the repo Github.


Function prototype related challenges


Function.prototype.call()

Solution 1: use Function.prototype.apply()
Solution 2: use Symbol

/**
 * @param {any} thisArg
 * @param {...*} argArray
 * @return {any}
 */

// Solution 1
// Time: O(1) | Space: O(1)
Function.prototype.myCall = function (thisArg, ...args) {
  return this.apply(thisArg, args);
};

// Solution 2
// Time: O(1) | Space: O(1)
Function.prototype.myCall = function (thisArg, ...argArray) {
  const sym = Symbol();
  const wrapperObj = Object(thisArg);

  Object.defineProperty(wrapperObj, sym, {
    enumerable: false,
    value: this,
  });

  return wrapperObj[sym](...argArray);
};

// Usage example
function multiplyAge(multiplier = 1) {
  return this.age * multiplier;
}

const mary = {
  age: 21,
};

const john = {
  age: 42,
};

console.log(multiplyAge.myCall(mary)); // => 21
console.log(multiplyAge.myCall(john, 2)); // => 84
Enter fullscreen mode Exit fullscreen mode

Function.prototype.apply()

Solution 1: use Function.prototype.call()
Solution 2: use Symbol

/**
 * @param thisArg The object to be used as the this object.
 * @param argArray A set of arguments to be passed to the function.
 * @return {any}
 */

// Solution 1
// Time: O(1) | Space: O(1)
Function.prototype.myApply = function (thisArg, argArray = []) {
  return this.call(thisArg, ...argArray);
};

// Solution 2
// Time: O(1) | Space: O(1)
Function.prototype.myApply = function (thisArg, argArray = []) {
  const sym = Symbol();
  const wrapperObj = Object(thisArg);

  Object.defineProperty(wrapperObj, sym, {
    enumerable: false,
    value: this,
  });

  return wrapperObj[sym](...argArray);
};

// Usage example
function multiplyAge(multiplier = 1) {
  return this.age * multiplier;
}

const mary = {
  age: 21,
};

const john = {
  age: 42,
};

console.log(multiplyAge.myApply(mary)); // 21
console.log(multiplyAge.myApply(john, [2])); // 84
Enter fullscreen mode Exit fullscreen mode

Function.prototype.bind()

Solution 1: use Function.prototype.call()
Solution 2: use Function.prototype.apply()
Solution 3: use Symbol

/**
 * @param {any} thisArg
 * @param {...*} argArray
 * @return {Function}
 */

// Solution 1
// Time: O(1) | Space: O(1)
Function.prototype.myBind = function (thisArg, argArray) {
  return (...innerArgs) => {
    return this.call(thisArg, ...argArray, ...innerArgs);
  };
};

// Solution 2
// Time: O(1) | Space: O(1)
Function.prototype.myBind = function (thisArg, argArray = []) {
  return (...innerArgs) => {
    return this.apply(thisArg, [...argArray, ...innerArgs]);
  };
};

// Solution 3
// Time: O(1) | Space: O(1)
Function.prototype.myBind = function (thisArg, ...argArray) {
  const sym = Symbol();
  const wrapperObj = Object(thisArg);

  Object.defineProperty(wrapperObj, sym, {
    enumerable: false,
    value: this,
  });

  return function (...args) {
    return wrapperObj[sym](...argArray, ...args);
  };
};

// Usage example
const john = {
  age: 42,
  getAge: function () {
    return this.age;
  },
};

const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // => undefined

const boundGetAge = john.getAge.myBind(john);
console.log(boundGetAge()); // => 42

const jack = {
  age: 21,
  getAge: function () {
    return this.age;
  },
};

// For multiple `.bind()` chaining, only the first one would work
const boundJohnGetAge = john.getAge.myBind(john).myBind(jack);
console.log(boundGetAge()); // => 42
Enter fullscreen mode Exit fullscreen mode

Reference

Top comments (0)