最近开始重新阅读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
// Examplevar 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 reducefunction unique(arr) { return arr.reduce( (prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]), [] );}
//using Es6 Setfunction 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; };}
//Examplelet 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
//Examplelet array = [[[1, [1.1]], 2, 3], [4, 5]] flatten(array)//[1, 1.1, 2, 3, 4, 5]
//reduce, recursivefunction flatten(arr) { return arr.reduce( (prev, curr) => { return prev.concat( Array.isArray(curr) ? flatten(curr) : curr ); }, []);}
//while loop, spread opeartorfunction 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