DEV Community

Cover image for Javascript method Implementation
WEI FENG
WEI FENG

Posted on • Updated on

Javascript method Implementation

"Let's take a deep dive to the most basic javascript method implementation. Hope it will help you to understand the language better"





1. Object.create()

The Object.create() method creates a new object, using an existing object as the prototype of the newly created object.

Object.prototype.newCreate = fucntion (obj) {
    // create a new function object as 
    function F(){}

    //bind the function object's prototype to the obj
    F.prototype = obj

    //return the newly created object based on F()
    return new F()
}
Enter fullscreen mode Exit fullscreen mode

2. instanceof

The instanceof operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object. The return value is a boolean value.

function myInstanceOf (left, right) {
    //access left object's prototype chain
    let leftProto = left.__proto__
    //access right constructor's prototype method
    let rightProto = right.prototype

    //check if rightProto is on the left object's prototype chain
    while (leftProto) {
        if (leftProto === rightProto) return true
        else leftProto = leftProto.__proto__
    }
    return false
}
Enter fullscreen mode Exit fullscreen mode

3. new

The new operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

function myNew (context, ...args) {
    //create a empty object 
    let obj = {}
    //link the new object's prototype chain to the constructor's prototype
    obj.__proto__ = context.prototype
    //call the constructor function on new object.
    let result = context.call(obj, ...args)
    return typeof result === "object" ? result : obj
}
Enter fullscreen mode Exit fullscreen mode

4. promise.all()

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the input's promises have resolved, or if the input iterable contains no promises. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.

//takes in an array of promises
function myPromiseAll(arr){
    // return a new promise
    return new Promise(function (resolve,reject) {
        let len = arr.length
        // setup a array to record the result
        let result = []
        let resolvedCount = 0
        for (let i = 0; i < len; i++) {
           //wrap the value from array in case it is not a promise 
           Promise.resolve(arr[i]).then(function(value){
               result[i] = value
               //resolve the result when finish resolving everything 
               resolvedCount++
              if (resolvedCount === len) return resolve(result)
          }, function(error) {
             // if there is an error, reject immediately
             return reject(error)
          })
       }
  })
}
Enter fullscreen mode Exit fullscreen mode

5. promise.race()

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

//takes in an array of promises
function myPromiseRace(arr){
    return new Promise(function (resolve,reject) {
        for (let i = 0; i < arr.length; i++) { 
           Promise.resolve(arr[i]).then(resolve, reject})
       }
  })
}
Enter fullscreen mode Exit fullscreen mode

6. Debounce function

The debounce() function forces a function to wait a certain amount of time before running again. The function is built to limit the number of times a function is called.

function debounce (func, delay) {
   // set a timer variable in the clousure to keep track
   let timer = null
   //return a debounced function
   return function debounced (...args) {
        //if timer is not null, clear the timer
        if (timer) {
                clearTimeout(timer)
                timer = null
            }
        //set a delay to run the function
        timer = setTimeout(()=> {
           func(...args)  
        }, delay)   
   }
}
Enter fullscreen mode Exit fullscreen mode

7. Throttle function

To throttle a function means to ensure that the function is called at most once in a specified time period (for instance, once every 10 seconds). This means throttling will prevent a function from running if it has run “recently”. Throttling also ensures a function is run regularly at a fixed rate.

function throttle (func, wait) {
    let timer = null
// set a flag in clousure to decide whether the current throttled program is running
    let flag = true

    return function throttled (...args) {
// if the flag is true, call the function and set the flag to false
        if (flag) {
            flag = false
            func(...args)
            timer = setTimeout(()=>{
            //set the flag back to true once finished waiting
                flag = true
                timer = null
            }, wait)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

8. Function.prototype.call()

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

Function.prototype.apply() is similar to call, we just need to change the seperate arguments to array.

Function.prototype.newCall = function (context, ...args) {
   // this is pointing to the function that call this newCall method, when we assign this function as context's property, this will point to the context.
    context.fn = this
    let result =  context.fn(...args)
    delete context.fn    
    return result
}
Enter fullscreen mode Exit fullscreen mode

9. Function.prototype.bind()

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.

Function.prototype.bind = function (context,...args) {
    let func = this
    //save the rest of the parameters
    return function binded (...rest) {
        //concat the arguments
        return func.call(context,...args,...rest)
    }
}
Enter fullscreen mode Exit fullscreen mode

10. a function to determine the type of an object

Using toString() to detect object class
toString() can be used with every object and (by default) allows you to get its class.
To use the Object.prototype.toString() with every object, you need to call Function.prototype.call() or Function.prototype.apply() on it, passing the object you want to inspect as the first parameter (called thisArg).

function typeOf(obj) {
// use array destructuring to extract the result
    let [,result] = Object.prototype.toString.call(obj).split(" ")
//slice out unnecessary characters
    return result.slice(0,-1)
}
Enter fullscreen mode Exit fullscreen mode

11. curried function

Currying is an advanced technique of working with functions. It’s used not only in JavaScript, but in other languages as well.
Currying is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c).
Currying doesn’t call a function. It just transforms it.

function curry (func) {
    return function curried (...args) {
      //compare the current arguments length with the function's required parameters. 
        if (args.length >= func.length){
            return func(...args)
        } else {
            // concat the rest of the arguments
            return function (...rest) {
                return curried(...args,...rest)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

12. AJAX request

AJAX update a web page without reloading the page
Request data from a server - after the page has loaded
Receive data from a server - after the page has loaded
Send data to a server - in the background

let url = "/server"

let xhr = new XMLHttpRequest();

xhr.open("GET", url, true)

xhr.onreadystatechange = function (){
// if readyState is 4 and status 200 means the request has been sucessfully executed. We can proceed to handle the response.
    if (this.readyState == 4 && this.status == 200) {
            handle(this.response)
        }
    }
}

xhr.onerror = function(){
    console.log(this.statusText)
}

xhr.send();
Enter fullscreen mode Exit fullscreen mode

wrap the ajax in a promise

function ajaxPromise (url) {
    return new Promise(function (resolve,reject) {
        let xhr = new XMLHttpRequest()
        xhr.open("GET", url, true)
        xhr.onreadystatechange = function () {
            if (this.readyState === 4 && this.status === 200) {
                return resolve(this.response)
            }
        }
        xhr.onerror = function(){
            return reject(this.statusText)
        }
        xhr.send()
    })
}
Enter fullscreen mode Exit fullscreen mode

13. Shallow Copy

  1. using slice
let arr = [1,2,3,4];
console.log(arr.slice()); // [1,2,3,4]

Enter fullscreen mode Exit fullscreen mode
  1. use spread operator
obj = {first: 1, 
       second: 2}
let cloneObj = { ...obj };
Enter fullscreen mode Exit fullscreen mode

14. Deep Copy

  1. handwritten deepcopy
function deepCopy (obj) {
     let newObj = Array.isArray(obj) ? [] : {}

     for (key in obj) {
         newObj[key]=typeof obj[key]==="object"?deepCopy(obj[key]):obj[key]
     }

    return newObj
}
Enter fullscreen mode Exit fullscreen mode
  1. JSON.parse(JSON.stringify(obj))

But this method has a problem. If there are functions, undefined, and symbols in the copied object, they will disappear after processing with JSON.stringify().

15. randomize the item sequence in array

function randomOutput(arr) {
    let len = arr.length
    for (let i = 0; i < len; i ++) {
        let randomNum = Math.floor(Math.random()*(len - i)) + i
        [arr[i], arr[randomNum]] = [arr[randomNum], arr[i]]
    }
    return arr
}
Enter fullscreen mode Exit fullscreen mode

16. How to flatten array

recursively flatten the array use array reduce method

function flatten (arr) {
    return arr.reduce((accum,element)=>{
        let flag = Array.isArray(element)
        return accum.concat(flag?flatten(element):element)
    },[])
}
Enter fullscreen mode Exit fullscreen mode

17. Event publisher and subscriber model

this is not a complete implementation

class EventEmitter {
    constructor () {
        this.events = {}
    }

    on (eventName, callbackFn) {
        if (!(eventName in this.events)) this.events[eventName] = []
        this.events[eventName].push(callbackFn)
    }

    emit (eventName, ...args) {
        this.events[eventName].forEach(fn => fn(...args))
    }

    off(eventName, callbackFn) {
        this.events[eventName] = this.events[eventName].filter(fn => fn != callbackFn && fn.initialCallback != callbackFn)
        if (this.events[eventName].length == 0) delete this.events[eventName]
    }

    once (eventName, callbackFn) {
        const one = (...args) => {
            callbackFn(...args)
            this.off(eventName, callbackFn)
        }
        one.initialCallback = callbackFn

        this.on(eventName, one)
    }
}
Enter fullscreen mode Exit fullscreen mode

18. Inherit from parent constructor

function Human (name,age) {
    this.name = name
    this.age = age
}

function Man (name,age) {
    Human.call(this,name,age)
}

Man.prototype = Object.create(Human.prototype)
Man.prototype.constructor = Man

Enter fullscreen mode Exit fullscreen mode

19.Convert Json to Tree

source = [{
            id: 1,
            pid: 0,
            name: 'body'
          }, {
            id: 2,
            pid: 1,
            name: 'title'
          }, {
            id: 3,
            pid: 2,
            name: 'div'
          }]

function toTree(src) {
    let map = {}
    src.forEach((ele)=>{
        map[ele["id"]] = ele
    })
    let result = []
    src.forEach((ele) => {
        let parent = map[ele.pid]
        if (parent) {
            if (!parent.children) parent.children = []
            parent.children.push(ele)
        } else {
            result.push(ele)
        }
    })


//Use React.createElement API

function tree(props){
  return React.createElement(props.name, props.props, props.children.map( child => tree(child)))
}
    return result
}
Enter fullscreen mode Exit fullscreen mode

20.Quick Sort

const quickSort1 = arr => {
    if (arr.length <= 1) {
        return arr;
    }
    //find the mid index
    const midIndex = Math.floor(arr.length / 2);
    //retrieve the mid index value
    const valArr = arr.splice(midIndex, 1);
    const midIndexVal = valArr[0];
    const left = []; //save those smaller than midIndexVal
    const right = []; //save those bigger than midIndexVal
    //iterate the array, push them into respective side. 
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] < midIndexVal) {
            left.push(arr[i]); 
        } else {
            right.push(arr[i]); 
        }
    }
    //recursively sort the array until array length < 1
    return quickSort1(left).concat(midIndexVal, quickSort1(right));
};
const array2 = [5, 4, 3, 2, 1];
console.log('quickSort1 ', quickSort1(array2));
// quickSort1: [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

21.Merge Sort
Image description

22.Create Element tree with react

function tree(props){
  return React.createElement(props.name, props.props, props.children.map( child => tree(child)))
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)