"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()
}
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
}
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
}
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)
})
}
})
}
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})
}
})
}
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)
}
}
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)
}
}
}
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
}
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)
}
}
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)
}
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)
}
}
}
}
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();
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()
})
}
13. Shallow Copy
- using slice
let arr = [1,2,3,4];
console.log(arr.slice()); // [1,2,3,4]
- use spread operator
obj = {first: 1,
second: 2}
let cloneObj = { ...obj };
14. Deep Copy
- 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
}
- 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
}
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)
},[])
}
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)
}
}
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
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
}
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]
22.Create Element tree with react
function tree(props){
return React.createElement(props.name, props.props, props.children.map( child => tree(child)))
}
Top comments (0)