iT邦幫忙

0

自己的輪子自己造--前端中的常見方法實作

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20221113/20148825pA7kq37tsy.jpg

最近開始重新閱讀JS的文章跟教學影片(網路上大推的Javascript: Understanding the weird parts),原因是想要把荒廢的JS基礎程式能力在練扎實一點,其中令我覺得學習到最多東西的部份就是JS的實作了!

因為在工作時,我們使用的工具很多時候網頁就有原生支援,或是我們會去使用像是lodash的套件,這樣的優點是開發上會很快速但是其實底下的原理我其實沒有實際去理解過,當然在正常情況下不知道底層實作對開發上是沒有影響的,就像是會開車的人也不需要懂車子架構的原理一樣,但是假如有天車子拋錨了,如果懂的如何換輪子來解決問題,相信對駕駛人來說一定不是壞事!所以秉持著這個心態,這篇文章就是要來紀錄我用JS來自己造輪子的過程!話不多說,下面就是我這次嘗試的實作:

部分實作在之前鐵人賽就有寫過更詳細介紹,有興趣的人可以去那裡看,這裡就會單純的放上程式碼。另外,這裡推薦讀者可以嘗試去自己寫看看,相信對你也是有幫助的!

Array method 實作

Array.prototype.map

Array.prototype.myMap = function (callback) {
  const result = [];
  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i], i, this));
  }
  return result;
};

Array.prototype.filter

Array.prototype.myFilter = function (callback) {
  const resultArray = [];
  for (let i = 0; i < this.length; i++) {
    if (!!callback(this[i], i, this)) {
      resultArray.push(this[index]);
    }
  }
  return resultArray;
};

Array.prototype.reduce

Array.prototype.myReduce = function (callback, initialValue) {
  let init = initialValue || this[0];
  let index = initialValue ? 0 : 1;
  for (let i = index; i < this.length; i++) {
    init = callback(init, this[i], i, this);
  }
  return init;
};

Promise 相關實作

Promise.all

function promiseAll(values) {
  if (!Array.isArray(values)) return;
  return new Promise((resolve, reject) => {
    let results = [];
    let completed = 0;

    values.forEach((value, index) => {
      Promise.resolve(value)
        .then((result) => {
          results[index] = result; // 確保回傳的Promise中,value的順序是對的!
          completed += 1;

          //如果成功的話就會回傳resolve
          if (completed == values.length) {
            resolve(results);
          }
        })
        .catch((err) => reject(err));
    });
  });
}

Promise.race

const PromiseRace = (values) => {
  return new Promise((resolve, reject) => {
    for (const item of values) {
      //第一個完成的會直接回傳
      Promise.resolve(item).then(resolve).catch(reject);
    }
  });
};

Promise
完整程式碼在下方的連結:

https://github.com/0529bill/promise-implementation/blob/master/simplePromise.js

優化method

https://0529bill.github.io/bywater-blog/ironMan2022/reactOptimization

debounce

function debounce(func, delay) {
  let timeout = null;
  return function (...args) {
    let context = this;
    //綁定在傳進來的func上
    clearTimeout(timeout);
    //清除掉前一個timeout

    timeout = setTimeout(function () {
      func.apply(context, args);
    }, delay);
  };
}

throttle

function throttle(func, delay) {
  let inThrottle;
  let timeout = null;
  return function (...args) {
    let context = this;
    if (!inThrottle) {
      func.apply(context, args);
      inThrottle = true;
      clearTimeout(timeout);
      timeout = setTimeout(function () {
        inThrottle = false;
      }, delay);
    }
  };
}

其他method

string轉成camelCase

camelCase(‘Foo Bar’) ==> ‘fooBar’

function camelCase(string) {
  if (typeof string !== "string") return;

  let newString = string.split("");
  for (let i = 0; i < newString.length; i++) {
    let currentString = newString[i];
//遇到空格的時候把下一個值轉為upperCase
    if (!currentString.trim().length) {
            newString.splice(i, 1)
            console.log('newString', newString)
            newString[i] = newString[i].toUpperCase()
        } else {
            newString[i] = currentString.toLowerCase()
        }
  }
  return newString.join("");
}

string轉成snakeCase

snakeCase(‘Foo Bar’) ==> ‘foo_bar’

function snakeCase(string) {
    if (typeof string !== 'string') return

    let newString = string.toLowerCase().split('')

    for (let i=0; i<string.length; i++) {
        let tempString = newString[i]
        if (!tempString.trim().length) {
            newString[i] = '_'
        }
    }
    return newString.join('')
}

unique value in an array

// Example

var arr = [
  1,
  1,
  "true",
  "true",
  true,
  true,
  15,
  15,
  false,
  false,
  undefined,
  undefined,
  null,
  null,
  NaN,
  NaN,
  "NaN",
  0,
  0,
  "a",
  "a",
  {},
  {},
];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]

//using reduce
function unique(arr) {
  return arr.reduce(
    (prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]),
    []
  );
}
//using Es6 Set
function unique(arr) {
  return Array.from(new Set(arr));
}

memoize function

function memoizeMap(fn) {
  const map = new Map();
  return function (arg) {
    if (map.has(arg)) {
      return map.get(arg);
    }
    const cachedArg = arg;
    const cachedResult = fn(arg);
    map.set(cachedArg, cachedResult);
    return cachedResult;
  };
}
//Example
let testFn = (foo) => foo + 999;

let memoizeMapFn = memoizeMap(testFn);

memoizeMapFn(1); // map對arg 1生成緩存
memoizeMapFn(1); // 取緩存結果
memoizeMapFn(1); // 取緩存結果

memoizeMapFn(2); // map對arg 2生成緩存
memoizeMapFn(2); // 取緩存結果
memoizeMapFn(1); // 取緩存結果

flatten an array

//Example

let array = [[[1, [1.1]], 2, 3], [4, 5]]  

flatten(array)
//[1, 1.1, 2, 3, 4, 5] 

//reduce, recursive
function flatten(arr) {
  return arr.reduce( (prev, curr)  => {
    return prev.concat(
      Array.isArray(curr) ? flatten(curr) : curr
    );
  }, []);
}
//while loop, spread opeartor
function flatten(arr) {
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}

Array轉JSON tree

function arrayToTree(items, baseLevelId) {
  const result = [];   
  const itemMap = {};   
    
  for (const item of items) {
    itemMap[item.id] = {...item, children: []}
  }
  
  for (const item of items) {
    const id = item.id;
    const pid = item.pid;
    const treeItem =  itemMap[id];
    if (pid === baseLevelId) {
      result.push(treeItem);
    } else {
      if (!itemMap[pid]) {
        itemMap[pid] = {
          children: [],
        }
      }
      itemMap[pid].children.push(treeItem)
    }}
  return result;
}

array轉JSON tree完整文章:

https://medium.com/@bywater529/%E7%94%A8%E4%B8%80%E9%A1%8C-js%E9%A1%8C%E6%B8%AC%E9%A9%97%E4%BD%A0%E6%98%AF%E5%89%8D%E4%BA%8C%E5%8D%81%E8%B6%B4%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%B8%AB%E9%82%84%E6%98%AF%E5%BE%8C%E4%B8%83%E5%8D%81%E8%B6%B4%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%B8%AB-8ff13186aa76

實現 instanceof

function _instanceof(L, R) {
  if (typeof L !== "object") return false;

  L = L.__proto__;
  R = R.prototype;

  while (true) {
    if (L === null) return false;

    if (L === R) return true;

    L = L.__proto__;
  }
}

資源:

https://0529bill.github.io/bywater-blog/Javascript/Basics/commonMethod


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言