最近自己撸了几个手写实现代码,记录一下。
节流函数
所谓节流函数,可以理解为一头鲸鱼定期要浮出水面呼吸,就是在固定的时间间隔内,无论执行多少次函数,都只会在间隔结束时执行一次。
function throttle(fn,delay){
let timer = null;
return function(){
let context = this;
let args = arguments;
if(timer){
return;
}
timer = setTimeout(function(){
fn.apply(context,args);
timer = null
},delay)
}
}
又或者用时间戳来判断
function throttle(fn,delay){
let pre = Date.now();
return function(){
let context = this;
let args = arguments;
let now = Date.now();
if(now-pre >= delay){
fn.apply(context,args);
pre= Date.now();
}
}
}
防抖函数
防抖函数,可以理解为在规定的时间内未执行第二次,则执行函数,否则就重置计时器,从新开始计算
function debounce(fn,delay){
let timer = null;
return function(){
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context,args);
},delay)
}
}
深拷贝方法
function deepClone(obj){
let copy = obj instanceof Array ? [] : {};
for(let i in obj){
if(obj.hasOwnProperty(i)){
copy[i] = typeof obj[i] == 'object' ? deepClone(obj[i]) : obj[i]
}
}
return copy;
}
实现一个基本的双向绑定
<!--html-->
<input id="input">
<span id="span"></span>
<!--js-->
let obj = {};
let input = document.getElementById('input');
let span = document.getElementById('span');
//对obj对象里面的text值进行数据劫持,检测到这个值发生变化,则触发get方法和set方法
Object.defineProperty(obj,"text",{
enumerable : true,
configurable : true,
set(newValue){
input.value = newValue;
span.innerHtml = newValue;
},
get(){
console.log("捕获到值")
}
})
//监听键盘事件
input.addEventListener('keyup',function(e){
obj.text = e.target.value;
})
实现一个new函数
function _new(obj,...rest){
//基于Obj的原型创建一个新的对象
let newObj = Object.create(obj.prototype);
//添加属性到新创建的newObj上,并获取obj函数的执行结果
let result = obj.apply(newObj,rest);
//如果执行结果有返回值并且是一个对象,返回执行的结果,否则返回创建的新对象
return typeof result =='object' && result!=null ? result : newObj
}
实现一个数据类型的判断函数
function typeOf(obj){
return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
let obj = {};
let arr = [];
typeOf(obj) //object
typeOf(arr) //array
实现把Json数据转换成树形结构
let arr = [
{ id: 1, name: "部门1", pid: 0 },
{ id: 2, name: "部门2", pid: 1 },
{ id: 3, name: "部门3", pid: 1 },
{ id: 4, name: "部门4", pid: 3 },
{ id: 5, name: "部门5", pid: 4 },
];
//不用递归的方法
function arr2Tree(data){
let result = [];
let map = {};
data.forEach((item,index)=>{
item.children = [];
map[item.id] = item;
if(item.pid == 0 || item.pid == ''){
result.push(item);
}else{
map[item.pid].children.push(item);
}
})
return result;
}
console.log(arr2Tree(arr));
重写一个call方法
Function.prototype.myCall = function(context){
if(typeof this !== 'function'){
throw new Error('not a function');
}
context = context || window;
context.fn = this;
let args = [...arguments].slice(1);
let result;
result = context.fn(...args);
delete context.fn;
return result;
}
重写一个apply方法
Function.prototype.myApply = function(context){
if(typeof this !== 'function'){
throw new Error('not a function');
}
context = context || window;
context.fn = this;
let args = arguments[1],result = '';
if(args){
result = context.fn(...args);
}else{
result = context.fn;
}
delete context.fn;
return result;
}