JavaScript高频手写题目(面试)

1 debounce

function debounce(fun, wait = 2000) {
  let timer = 0;
  return function(...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => { fun.aplly(this, args) }, wait)
  }
}

2 throttle

function throttle(fun, wait= 2000){
  let lastTime = 0;
  return function (...args) {
    let now = + new Date();
    if (now - lastTime > wait){
      fun.apply(this, args);
      lastTime = now;
    }
  }
}

3 deepclone

3.1 json
  • 无法实现对函数 、RegExp等特殊对象的克隆
  • 会抛弃对象的constructor,所有的构造函数会指向Object
  • 对象有循环引用,会报错
const newObj = JSON.parse(JSON.stringify(oldObje));
3.2 递归
function deepClone(obj) {
  let res = obj;
  if(typeof(obj) !== 'object') return res;
  
  res = Array.isArray(obj) ? [] : {};
  for(let i in obj) {
    res[i] = typeof(obj[i]) === 'object' ? deepClone(obj[i]) : obj[i];
  }
  return res;
}

4 Event(event bus)

event bus既是node中各个模块的基石,又是前端组件通信的依赖手段之一,同时涉及了订阅-发布设计模式,是非常重要的基础

class EventEmitter {
  constructor() {
    this._events = this._event || new Map(); //存储事件
    this._maxListeners = this._maxListeners || 10; //监听上限
  }
  
  //触发监听名为type的事件
  emit(type, ...args) {
    let events = this._events.get(type);
    if (!events) return;
    for (let i = 0; i < events.length; i++) {
      events[i].apply(this, args);
    };
  }
  
 	//添加监听名为type的事件fun
  addListener(type, fun) {
    let events = this._events.get(type);
    if (events) {
      events.push(fn);
    } else {
    	this._events.set(type, [fun]);
    };
  }
  
  //移除监听名为type的事件fun
  removeListener(type, fun) {
  	let events = this._events.get(type);
    if (!event) return;
    for (let i = 0; i < events.length; i++) {
    	 if (events[i] === fn) {
         events.splice(i, 1);
         if (events.length === 0) events = null;
       };
    };
  }
}



5 new function

Object.create(proto, [propertiesObject])
//方法创建一个新对象,使用现有的对象来提供新创建的对象的proto

//模拟 new 操作符
function myNew(fn, ...args) {
  //1、创建一个空对象并把空对象 __proto__ 指向构造函数的 prototype
  let instance = Object.create(fn.prototype);
  //2、执行构造函数
  let res = fn.apply(instance, args);
  //3、返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象
  return typeof res === 'object' ? res: instance;
}

6 promise

function myPromise(fun) {
  this.status = 'pending';
  this.value = undefined;
  this.reason = undefined;
  
  //私有方法
  let resolve = (value) => {
    if (this.status === 'pending') {
      this.value = value;
      this.status = 'resolved'
    }
  };
  let reject = (reason) => {
    if (this.status === 'pending') {
      this.reason = reason;
      this.status = 'rejected';
    } 
  }
  
  //添加 then 方法
  this.then = function(onFullfilled, onRejected) {
    switch(this.status) {
      case 'resolved':
        onFullfilled(this.value);
        break;
      case 'rejected':
         onRejected(this.reason);
        break;
      default:
    }
  }
  
 	try {
    fun(resolve, reject);
  } catch(e) {
    reject(e);
  }
}

7 模版渲染

function render(template, data) {
  const reg = /\{\{(\w+)\}\}/;
	while (reg.test(template)) {
    const name = reg.exec(template)[1];
    if (ata[name]) template = template.replace(reg, data[name])
  }
	return template;
}

//测试
let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
  name: '姓名',
  age: 18
}
render(template, data);

8 转驼峰命名

let str = 'get-element-by-id';
function toCamel(str) {
  return str.replace(/-\w/g, (item) => item.slice(1).toUpperCase());
}

9 字符串

9.1 最多字符
let str = "abcabcabcbbccccc";
let num = 0;
let char = '';
str = str.split('').sort().join('');
let re = /(\w)\1+/g;
str.replace(re,($0,$1) => {
    if(num < $0.length){
        num = $0.length;
        char = $1;        
    }
});
console.log(`字符最多的是${char},出现了${num}次`);
9.2 千分位分隔符
function parseToMoney(num) {
  let [integer, decimal] = num.toFixed(2).split('.');
  integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,');
  return integer + '.' + decimal;
} 

10 flat

10.1 Array.prototype.flat()

flat( )用于将嵌套的数组“拉平”,变成一维数组。该方法返回一个新数组,对原数据没有影响。

参数表示展开层数,infinity 不管多少层都会展开

let res = [1, 2, [3, [4]]].flat(infinity);	//[1, 2, 3, 4]
10.2 递归
function myFlat (arr) {
  let res = []; //res要定义在递归函数外
  function fun(arr) {
    arr.map(item => {
      Array.isArray(item) ? fun(item) : res.push(item)
    })
  };
 	fun(arr);
  return res;
}
10.3 reduce
function myFlate(arr) {
  return arr.reduce((pre, cur) => {
    return pre.concat(Array.isArray(cur) ? myFlate(cur) :  cur )
  }, []);
}
10.4 扩展运算符
while(arr.some(Array.isArray)) {
	arr = [].concat(...arr)
}

11 sleep

function sleep(wait = 1000) {
  return new Promise(resolve => setTimeout(resolve, timer));
}

12 双向数据绑定

12.1 defineProperty

Object.defineProperty (对象名,对象属性,属性描述器)

const data = { text: 'default' };

const input = document.getElementById('input');
const span = document.getElementById('span');

//数据挟持,数据变化 =》 修改视图
Object.defineProperty(data, 'text', {
  configurable: true, //是否能被修改
  enumerable: true, //是否可遍历
  get() { //获取data 'text' 属性时候调用 get()且 data.text = 123;
  	return 123;
  },
  set(newVal) { //每次给对象属性赋值的时候会调用这个函数
    input.value = newVal;
    span.innerHTML = newVal;
  }
});

//视图改变 =》数据变化
input.addEventListener('keyup', function(e) => {
	data.text = e.target.value;                       
})
12.2 proxy
const data = { text: 'default' };

const input = document.getElmentById('input');
const span = document.getElmentById('span');

const handler = {
  set(target, key, value) {
    target[key] = value;
    span.innerHTML = value;
    return value;
  }
}

const proxy = new Proxy(data, hanler);

input.addEventListener('keyup', function(e) {
	proxy.text = e.target.value;
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值