网站首页 > 技术文章 正文
JavaScript笔试部分
本文分享 12 道高频JavaScript的面试题,包含手写以及常用的正则。
实现防抖函数 (debounce)
防抖函数原理 : 在事件被触发n秒后在执行回调,如果在这n秒内又被触发,则重新计时。
那么与节流函数的区别直接看这个动画实现即可。
手写简化版
//防抖函数const debounce = (fn,delay)=>{ let timer = null; return (...args)=>{ clearTimeout(timer); timer = setTimeout(()=>{ fn.apply(this,args) },delay); };};
适用场景 :
- 按钮提交场景: 防止多次提交按钮,只执行最后提交的一次
- 服务端验证场景 : 表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似
生存环境请用lodash.debounce
实现节流函数 (throttle)
防抖函数原理:规定在一单位时间内。只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
//手写简化版
//节流函数const throttle = (fn,delay = 500) =>{ let flag = true; return (...args) =>{ if (!flag) return; flag = false; setTimeout(() => { fn.apply(this,args) },delay); };};
适用场景:
- 拖拽场景: 固定时间内只执行一次,防止超高频次触发位置变动
- 缩放场景: 监控浏览器resize
- 动画场景: 避免短时间内多次触发动画引起性能问题
深克隆 (deepclone)
简单版 :
const newObj = JSON.parse(JSON.stringify(oldObj));
局限性 :1、他无法实现函数、RegExp等特殊对象的克隆
2、会抛弃对象的constructor,所有的构造函数会指向Object
3、对象有循环引用,会报错
实现Event (event bus)
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
//模拟 instanceoffunction 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
new操作符做了这些事:
- 他创建了一个全新的对象
- 他会被执行[[Prototype]] (也就是__proto__) 链接
- 它使this指向新创建的对象
- 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上
- 如果函数没有返回对象类型Object(包含Function,Array,Date,RegExg,Error),那么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做了什么 :
- 将函数设为对象的属性
- 执行&删除这个函数
- 指定this到函数并传人给定参数执行函数
- 如果不传入参数,默认指向为 window
//模拟 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方法
apply原理与call很相似,不多獒数
//模拟 applyFunction.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
实现bind要做什么
返回一个函数,绑定this,传递预置参数
bind返回的函数可以作为构造函数使用。故作为构造函数时应使得this失效,但是传人的参数依然// 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.createObject.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。// 模拟 Object.createfunction create(proto) { function F() {} F.prototype = proto; return new F();}
模拟Object.create
Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
// 模拟 object.create
function create(proto){ function F(){ F.prototype = proto; return new F(); }}
解析 URL Params为对象
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(); })}
本文主要是一些基础知识,希望能帮助那些基础不太好的同行们。加油~~~~~~
猜你喜欢
- 2024-10-05 前端面试,你有必要知道的一些JavaScript 面试题(上)
- 2024-10-05 几道看起来代码量很少的Javascript笔试题,看看你会不会做?
- 2024-10-05 前端面试题《JS基础》 前端面试 js
- 2024-10-05 前端面试题JavaScript 前端面试题目100及最佳答案
- 2024-10-05 day6:前端面试题(js) js前端面试题及答案
- 2024-10-05 2023年最新的JavaScript面试题 锦屏县2023年幼儿园面试题
- 2024-10-05 20个基本的JavaScript面试问题及答案
- 2024-10-05 逐渐深入的Javascript面试题,看看你能过几关?
- 2024-10-05 谷歌面试7个简单又棘手的前端JavaScript面试题
- 2024-10-05 day10:前端面试题(js) 前端面试题及答案 知乎
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle约束 (46)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)