G - I 系列
获取元素距离顶部的距离
1const getVerticalOffset = el => { 2 let offset = el.offsetTop, 3 _el = el; 4 while (_el.offsetParent) { 5 _el = _el.offsetParent; 6 offset += _el.offsetTop; 7 } 8 return offset; 9};
- offsetTop 是相对其父元素的距离,这里主要通过累加的方式来获取
- 对于嵌套较深的节点,可能其他 api (元素位置信息)来的更快些
根据给定函数对数组元素进行分组
1const groupBy = (arr, fn) => 2 arr 3 .map(typeof fn === 'function' ? fn : val => val[fn]) 4 .reduce((acc, val, i) => { 5 acc[val] = (acc[val] || []).concat(arr[i]); 6 return acc; 7 }, {}); 8 9groupBy([6.1, 4.2, 6.3], Math.floor); // {4: [4.2], 6: [6.1, 6.3]} 10groupBy(['one', 'two', 'three'], 'length'); // {3: ['one', 'two'], 5: ['three']}
- 第一次 map 的时候就将分组条件划分为一个数组
- reduce 时再以,条件做为key值,往其中添加值
检查一维数组中是否有重复的值
1const hasDuplicates = arr => new Set(arr).size !== arr.length; 2 3hasDuplicates([0, 1, 1, 2]); // true 4hasDuplicates([0, 1, 2, 3]); // false
- 转化为 Set 对象,再通过size与原数组是否相等
- Set 后就去重了,size可理解为长度
检查是否为绝对url格式
1const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); 2 3isAbsoluteURL('https://google.com'); // true 4isAbsoluteURL('ftp://www.myserver.net'); // true 5isAbsoluteURL('/foo/bar'); // false
类数组的检查
1const isArrayLike = obj => 2 obj != null && typeof obj[Symbol.iterator] === 'function'; 3 4 5isArrayLike([1, 2, 3]); // true 6isArrayLike(document.querySelectorAll('.className')); // true 7isArrayLike('abc'); // true 8isArrayLike(null); // false
检查一个函数是否是异步函数
1const isAsyncFunction = val => 2 Object.prototype.toString.call(val) === '[object AsyncFunction]'; 3 4isAsyncFunction(function() {}); // false 5isAsyncFunction(async function() {}); // true 6 7// 类型为 AsyncFunction,类似的还要检查是否为 Promise 8 9const isPromiseLike = obj => 10 obj !== null && 11 (typeof obj === 'object' || typeof obj === 'function') && 12 typeof obj.then === 'function'; 13 14isPromiseLike({ 15 then: function() { 16 return ''; 17 } 18}); // true 19isPromiseLike(null); // false 20isPromiseLike({}); // false
判断当前页面是否可见
1const isBrowserTabFocused = () => !document.hidden; 2 3isBrowserTabFocused(); // true 4// 更多依赖 Page Visibility 这个API吧,权当了解下
检查值是否是有下铺的JSON
1const isValidJSON = str => { 2 try { 3 JSON.parse(str); 4 return true; 5 } catch (e) { 6 return false; 7 } 8}; 9// 之前同时事也问过此问题,当时确定没想到可以 try catch 的方式来判断 10 11isValidJSON('{"name":"Adam","age":20}'); // true 12isValidJSON('{"name":"Adam",age:"20"}'); // false 13isValidJSON(null); // true
实现一个 findIndex
1const linearSearch = (arr, item) => { 2 for (const i in arr) { 3 if (arr[i] === item) return +i; 4 } 5 return -1; 6}; 7 8linearSearch([2, 9, 9], 9); // 1 9linearSearch([2, 9, 9], 7); // -1
实现事件一次绑定
1// 这个是运用添加事件参数实现的 2const listenOnce = (el, evt, fn) => 3 el.addEventListener(evt, fn, { once: true }); 4 // 可以传入 option(对象) 也可以传入 useCapture(布尔) 5 6listenOnce( 7 document.getElementById('my-id'), 8 'click', 9 () => console.log('Hello world') 10); 11// 通过闭包函数实现 12const once = fn => { 13 let called = false; 14 return function(...args) { 15 if (called) return; 16 called = true; 17 return fn.apply(this, args); 18 }; 19}; 20 21const startApp = function(event) { 22 console.log(this, event); // document.body, MouseEvent 23}; 24document.body.addEventListener('click', once(startApp)); 25 26// 现在多数框架也有对应实现,比如 VUE @click.once,起初并未运用,也没想过实现原理,现在知道了,好像也不难实现 哈哈
实现一个缓存(记忆)函数
1const memoize = fn => { 2 const cache = new Map(); 3 const cached = function (val) { 4 return cache.has(val) 5 ? cache.get(val) 6 : cache.set(val, fn.call(this, val)) && cache.get(val); 7 // && 返回cache.get(val),如果是比较,&&的才返回布尔值 8 }; 9 cached.cache = cache; 10 return cached; 11}; 12 13// See the `anagrams` snippet. 14const anagramsCached = memoize(anagrams); 15anagramsCached('javascript'); // takes a long time 16anagramsCached('javascript'); // returns virtually instantly since it's cached 17console.log(anagramsCached.cache); // The cached anagrams map
将对象转换成查询字符串形式 ?key=value&xxx=aaa
1// Object.entries 直接将对象转为 数组形式的 key-value 2const objectToQueryString = queryParameters => { 3 return queryParameters 4 ? Object.entries(queryParameters).reduce( 5 (queryString, [key, val], index) => { 6 const symbol = queryString.length === 0 ? '?' : '&'; 7 queryString += 8 typeof val === 'string' ? `${symbol}${key}=${val}` : ''; 9 return queryString; 10 }, 11 '' 12 ) 13 : ''; 14}; 15objectToQueryString({ page: '1', size: '2kg', key: undefined }); 16// '?page=1&size=2kg'
