函数技巧总结
记录一些实用的函数技巧
包含大量实用函数,持续更新中。
1、尤大的强绑bind实现(据说比原生还快一点)
//传入强绑函数与上下文 function bind(fn, ctx) { function boundFn(a) { var l = arguments.length; //根据传参数执行函数 return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx) } //保存传入函数形参数 boundFn._length = fn.length; return boundFn } //示例 var obj = { a: 1 } var fn = bind(function(n1, n2) { console.log(this.a); console.log(n1 + n2); }, obj); fn(1, 2); //1 3
使用方法也很简答,传入函数与强绑上下文,再传入参数执行。
2、事件触发节流阀
该方法来源于伟大的jQuery作者,john ***!
// 节流函数与最低触发事件 function delayFn(fn, delay) { var timer = false; // 滚动触发 window.onscroll = function() { timer = true; }; // 每隔一段时间触发指定函数 setInterval(function() { if (timer) { timer = false; fn(); } }, delay); }
这个函数也相当简单,用于滚动事件的监听。由于滚动会非常频繁的触发onscroll,所以设定一个触发频率可以极大的优化浏览器性能。
3、缓步加载函数
该函数应用场景主要是后台提供了大量的数据需要渲染到页面,然而直接拼接字符串+innerHTML会导致假卡死,用户体验极差。
虽然说这个问题的源头就是错误的,但是也有一些补救的办法。
// 假设通过ajax请求到一个包含大量数据的数组 ajax('url', function(result) { var data = result; fps(data, 1000, 1000, function(data) { console.log(data); }); }); // cut为每次处理的数量 // delay为每次处理的间隔时间 function fps(data, cut, delay, fn) { // 对剩余数量做检测 var res = data.length < cut ? data.splice(0, data.length) : data.splice(0, cut); fn(res); if (data.length > 0) { // 下一批数据的处理会在下一个task中进行 setTimeout(fps, delay); } }
自己手写的,比较简单,大概思想出来就好了嘛~
4、插入一个深拷贝函数
// 接受变量与类型 function type(el, type) { return Object.prototype.toString.call(el).slice(8, -1) === type; } // 深拷贝 目标对象与拷贝对象 function deepCopy(tar, obj) { var tar = tar || {}, el, clone; for (var key in obj) { el = obj[key]; if (type(el, 'Object') || type(el, 'Array')) { clone = type(el, 'Object') ? {} : []; tar[key] = deepCopy(clone, el); } else { tar[key] = el; } } return tar; } // 使用方法 var obj = { a: [1], b: { a: 1 } }; var obj2 = {}; deepCopy(obj2, obj);
5、数组去重
来自于jQuery源码:
// 去重 function duplicate(arr) { var len = arr.length, num = 0, res = []; // 先进行排序 arr.sort((a, b) => a - b); // 找出所有相邻重复元素索引 for (var i = 0; i < len; i++) { if (arr[i] === arr[i + 1]) { res.push(i); num++; } } //依次删除 while (num--) { arr.splice(res[num], 1); } return arr; }
6、数组乱序
打乱数组,俗称洗牌,方法超级简单易懂,但是可能很low。没关系!可以多循环几次!
// 返回随机数 function getR(len) { return Math.floor(Math.random() * len); } // 打乱数组 function randomArr(arr) { var len = arr.length, j; for (var i = 0; i < len; i++) { // 获取随机索引 j = getR(len); // 交换位置 [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; }
7、缓存函数
来源于vue源码:
// 有时候可能需要默认缓存对象 function cached(fn, cache) { var cache = cache || Object.create(null); // 返回一个函数 return (function cachedFn(str) { var hit = cache[str]; return hit || (cache[str] = fn(str)) }) }
默认情况下创建一个纯净对象用来做缓存,当然也可以选择自己传入一个带有默认值得缓存对象。
8、惰性求值函数
适用于兼容性判断,第一次加载重写函数,第二次跳过判断逻辑。
var a = 1; // 惰性加载函数 function lazy(el) { // 第一次做判断 if (el === 1) { // 然后重写函数 lazy = function() { return 1; } } else if (el === 2) { lazy = function() { return 2; } } return lazy(); } console.log(lazy(a)); //1 // 第二次调用跳过判断环节 console.log(lazy(a)); //1 console.log(lazy(a)); //1 console.log(lazy(a)); //1 console.log(lazy(a)); //1
9、遍历DOM树
超级简单!!!一看就会
// 遍历DOM树 function walkDom(node, fn) { fn(node); // 使用该方法避免回车会导致空行 node = node.firstElementChild; while (node) { walkDom(node, fn); node = node.nextElementSibling; } } // 示例 var div = document.getElementsByTagName('div')[0]; walkDom(div, function(el) { console.log(el.tagName); });
10、快速生成16进制颜色
超级简单!!!
function getHexColor() { return '#' + Math.random().toString(16).substr(2, 6); }
先写这几个了!
老子要日穿V8引擎