本文分享 12 道高频JavaScript的面试题,包含手写以及经常使用的正则。前端
防抖函数原理 : 在事件被触发n秒后在执行回调,若是在这n秒内又被触发,则从新计时。node
那么与节流函数的区别直接看这个动画实现便可。 面试
手写简化版设计模式
//防抖函数 const debounce = (fn,delay)=>{ let timer = null; return (...args)=>{ clearTimeout(timer); timer = setTimeout(()=>{ fn.apply(this,args) },delay); }; }; 复制代码
适用场景 :数组
生存环境请用lodash.debounce浏览器
防抖函数原理:规定在一单位时间内。只能触发一次函数。若是这个单位时间内触发屡次函数,只有一次生效。bash
//手写简化版markdown
//节流函数 const throttle = (fn,delay = 500) =>{ let flag = true; return (...args) =>{ if (!flag) return; flag = false; setTimeout(() => { fn.apply(this,args) },delay); }; }; 复制代码
适用场景:app
简单版 :dom
const newObj = JSON.parse(JSON.stringify(oldObj));
复制代码
局限性 : 一、他没法实现函数、RegExp等特殊对象的克隆
二、会抛弃对象的constructor,全部的构造函数会指向Object
三、对象有循环引用,会报错
event bus既是node中各个模块的基石,又是前端组件通讯的依赖手段之一,同时涉及了订阅-发布设计模式,是很是重要的基础。
简单版:
class EventEmeitter { constructor(){ this._events = this._events || new Map(); //储存事件/回调键值对 this._maxListeners = this._maxListeners || 1o;//设立监听上限 } } //触发名为type的事件 EventEmeitter.prototype.emit = function(type,...args){ let hander; //从储存事件键值对的this._events中获取对应事件回调函数 handler = this._events.get(type); if (args.length > 0) { hander.apply(this,args); }else{ handler.call(this); } return true; }; //监听名为type事件 EventEmeitter.prototype.addListener = function(type,fn) { //将type事件以及对应的fn函数放入this._events中储存 if (!this._events.get(type)) { this._events.set(type,fn); } }; 复制代码
//模拟 instanceof function instance_of(L,R){ var O = R.prototype;//取 R 的显示原型 L = L.__proto__;//取 L 的隐式原型 while (true) { if (L === null) return false; if (O === L) // 这里重点 : 当 O 严格等于 L 时,返回 true return true; L = L.__proto__; } } 复制代码
new操做符作了这些事:
// objectFactory(name,'cxk','18') function objectFactory(){ const obj = new object(); const Constructor = [].shift.call(arguments); obj.__proto__ = Constructor.prototype; const ret = Constructor.apply(obj,arguments); return typeof ret === "object" ? ret : obj; } 复制代码
call作了什么 :
//模拟 call bar.mycall(null); //实现一个call方法; Function.prototype.myCall = function(context){ //此处没有考虑context非object状况 context.fn = this; let args = []; for (let i = 1,len = arguments.length,i < len; i++){ args.push(arguments[i]); } context.fn(...args); let result = context.fn(...args); delete context.fn; return result; }; 复制代码
apply原理与call很类似,很少獒数
//模拟 apply Function.prototype.myapply = function(context,arr){ var context = Object(context) || window; context.fn = this; var result; if (!arr){ result = context.fn(); }else{ var args = []; for (var i = 0,len = arr.length;i < len; i++){ args.push("arr["+ i +"]"); } result = eval("context.fn("+ args + ")"); } delete context.fn; return result; } 复制代码
实现bind要作什么
// mdn的实现 if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'function') { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { // this instanceof fBound === true时,说明返回的fBound被当作new的构造函数调用 return fToBind.apply(this instanceof fBound ? this : oThis, // 获取调用时(fBound)的传参.bind 返回的函数入参每每是这么传递的 aArgs.concat(Array.prototype.slice.call(arguments))); }; // 维护原型关系 if (this.prototype) { } // 下行的代码使fBound.prototype是fNOP的实例,所以 // 返回的fBound若做为new的构造函数,new生成的新对象做为this传入fBound,新对象的__proto__就是fNOP的实例 fBound.prototype = new fNOP(); return fBound; }; } 复制代码 详解请移步JavaScript深刻之bind的模拟实现 #12 模拟Object.create Object.create()方法建立一个新对象,使用现有的对象来提供新建立的对象的__proto__。 // 模拟 Object.create function create(proto) { function F() {} F.prototype = proto; return new F(); } 复制代码
Object.create() 方法建立一个新对象,使用现有的对象来提供新建立的对象的__proto__。
// 模拟 object.create function create(proto){ function F(){ F.prototype = proto; return new F(); } } 复制代码
let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled'; parseParam(url) /* 结果 { user: 'anonymous', id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型 city: '北京', // 中文需解码 enabled: true, // 未指定值得 key 约定为 true } */ 复制代码
var s1 = "get-element-by-id" //转化为 getElementById 复制代码
var f = function(s){ return s.replace(/-\w/g,function(x){ return x.slice(1).toUpperCase(); }) } 复制代码