js高频手撸代码题总结

javascript

1、什么是防抖和节流,他们的应用场景有哪些

防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

示例代码:

function debounce(fn,wait){
    let timer;
    return function(...args){
        let _this=this;
        if(timer){
            clearTimeout(timer)
        }

        timer=setTimeout(() => {
            fn.apply(_this,args)
        }, wait);
    }
}
window.onresize = debounce(function() {console.log('resize')}, 500)

应用场景:
a、登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
b、调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
c、文本编辑器实时保存,当无任何更改操作一秒后进行保存

节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

示例代码:

function throttle(fn,wait){
    let preTime=Date.now();
    return function(...args){
        let _this=this;
        let nowTime=Date.now();
        if(nowTime-preTime>=wait){
            fn.apply(_this,args)
            preTime=Date.now();
        }
    }
}

应用场景:
a、懒加载、滚动加载、加载更多或监听滚动条位置;
b、百度搜索框,搜索联想功能;
c、防止高频点击提交,防止表单重复提交;

2、对象深度克隆的简单实现

function deepClone(object){
	if(!object||typeof object !=='object') return;
	let newObject=Array.isArray(object)? []:{};
	for(let key in object){
		if(object.hasOwnProperty(key)){
			newObject[key]=
			typeof object[key]==='object'? deepClone(object[key]):object[key]	
		}
	}
	return newObject;
}

3、实现一个 once 函数,传入函数参数只执行一次

function once(fun){
    let tag=true;
    return function(...args){
        if(tag===true){
            fun.apply(null,args)
            tag=false
        }
        return undefined;
    }
}

4、实现一个bind函数

Function.prototype.myBind=function(context){
    if(typeof this!=='function'){
        throw new TypeError('Error');
    }
    let args=[...arguments].slice(1), //或者Array.prototype.slice.call(arguments,1)
    fn=this;
    return function Fn(){
        return fn.apply(this instanceof Fn? this:context,args.concat(...arguments))
    }
}

5、实现一个sleep函数

/**
 * promise
 */
 function sleep(ms){
    let temple=new Promise(resolve=>{
        setTimeout(resolve,ms)
    })
    return temple;
  }
  sleep(2000).then(()=>{
      console.log('开始执行')
  })
/**
 * async
 */
  function sleep2(ms){
      return new Promise(resolve=>{
          setTimeout(resolve,ms);
      })
  }
  async function test(){
      let temple=await sleep2(2000)
      console.log('开始执行,async')
      return temple;
  }
  test()

  /**
   * generate
   */
  function *sleep3(ms){
    yield  new Promise(resolve=>{
        setTimeout(resolve,ms);
    })
  }
  sleep3(2000).next().value.then(function(){
      console.log('开始执行,generate')
  })

6、手写一个简单的promise

function myPromise(constructor){
  let self=this;
  self.status='pending'
  self.value=undefined
  self.reason=undefined
  function resolve(value){
      //两个==='pending',保证了状态的改变是不可逆的
      if(self.status==='pending'){
          self.value=value;
          self.status='resolved'
      }
  }
  function reject(reason){
      //两个==='pending',保证了状态的改变是不可逆的
      if(self.status==='pending'){
          self.reason=reason;
          self.status='rejected';
      }
  }
  //捕获构造异常
  try{
      constructor(resolve,reject);
  }catch(e){
      reject(e)
  }
}
myPromise.prototype.then=function(onFullfilled,onRejected){
  let self=this;
  switch(self.status){
      case "resolved":
          onFullfilled(self.value);
          break;
      case "rejected":
          onRejected(self.reason);
          break;
      default:    
  }
}
var p=new myPromise(function(resolve,reject){resolve(1)});
p.then(function(x){console.log(x)})

7、js实现全排列算法(给定一个字符串,输出该字符串所有排列的可能。如输入“abc”,输出“abc,acb,bca,bac,cab,cba”)

function permutate(str) {
    var result = [];
    if (str.length > 1) {
      //遍历每一项
      for (var m = 0; m < str.length; m++) {
        //拿到当前的元素
        var left = str[m];
        //除当前元素的其他元素组合
        var rest = str.slice(0, m) + str.slice(m + 1, str.length);
        //上一次递归返回的全排列
        var preResult = permutate(rest);
        //组合在一起
        for (var i = 0; i < preResult.length; i++) {
          var tmp = left + preResult[i]
          result.push(tmp);
        }
      }
    } else if (str.length == 1) {
       result.push(str);
    }
    return result;
   }
   
console.log(permutate('abcd'))

8、使用闭包实现一个单例模式

单例模式的定义: 保证一个类仅有一个一个实例,并提供一个访问它的全局访问点。

应用场景:
单例模式能在合适的时候创建对象,并且创建唯一的一个。
代码接近于生活,很有意思。比如一个网站的登录,点击登录后弹出一个登录弹框,即使再次点击,也不会再出现一个相同的弹框。又或者一个音乐播放程序,如果用户打开了一个音乐,又想打开一个音乐,那么之前的播放界面就会自动关闭,切换到当前的播放界面。这些都是单例模式的应用场景。
要实现一个单例模式,一个经典的方式是创建一个类,类中又一个方法能创建该类的实例对象,还有一个标记,记录是否已经创了过了实例对象。如果对象已经存在,就返回第一次实例化对象的引用。
代码示例:

var Singleton = (function () {
    var instance;
    var CreateSingleton = function (name) {
        this.name = name;
        if (instance) {
            return instance; 
        }
        // 打印实例名字
        this.getName(); 
        // instance = this;
        // return instance; 
        return instance = this; 
    }// 获取实例的名字
    CreateSingleton.prototype.getName = function() { 
        console.log(this.name) 
    }
    return CreateSingleton; 
})(); 
    // 创建实例对象 1 
var a = new Singleton('a'); 
// 创建实例对象 2
var b = new Singleton('b');
console.log(a===b) //true
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值