文章插图
在面试中,常常会遇到一些手写XXX之类的面试题,因此好好总结一下,对于巩固我们的原生js的基础是非常必要的 。
尽管在网上已经有了非常多的总结文章,但在我看来有一个普遍的问题,那就是把原理性的东西过于复杂化了 。如果站在面试官的角度,他的目的是在最短的时间内考察出面试者对于JS语言的理解程度,但是在看了网站的诸多总结文章后我发现其中的代码有很大一部分是做意义不大的操作,比如实现一个简单的防抖,只要是核心的流程展示即可,至于其他的一些等模式则没有必要再去深挖,一大堆的if-else让人看上去也眼花缭乱,甚至误导别人直接去背代码,另外,核心的逻辑都能展示出来,再去横向的实现其他的类似情况恐怕也不是什么问题了 。
在以下的整理中,建议大家先照的核心要点自己写一遍,然后对照下面的代码,复习效果更好 。本文的目的就在于以最简洁的代码帮你从第一性原理的角度理解api的内部运作流程,凡是对于我们理解api没有帮助的的边界情况都不做处理 。
一、用ES5实现数组的map方法核心要点:
1.回调函数的参数有哪些,返回值如何处理 。
2.不修改原来的数组 。
Array.prototype.MyMap = function(fn, context){ var arr = Array.prototype.slice.call(this);//由于是ES5所以就不用...展开符了 var mAppedArr = []; for (var i = 0; i < arr.length; i++ ){ mappedArr.push(fn.call(context, arr[i], i, this)); } return mappedArr;}二、用ES5实现数组的reduce方法核心要点:
1、初始值不传怎么处理
2、回调函数的参数有哪些,返回值如何处理 。
Array.prototype.myReduce = function(fn, initialValue) { var arr = Array.prototype.slice.call(this); var res, startIndex; res = initialValue ? initialValue : arr[0]; startIndex = initialValue ? 0 : 1; for(var i = startIndex; i < arr.length; i++) { res = fn.call(null, res, arr[i], i, this); } return res;}三、实现call/apply思路: 利用this的上下文特性 。
//实现apply只要把下一行中的...args换成args即可Function.prototype.myCall = function(context = window, ...args) { let func = this; let fn = Symbol("fn"); context[fn] = func; let res = context[fn](...args "fn");//重点代码,利用this指向,相当于context.caller(...args) delete context[fn]; return res;}四、实现Object.create方法(常用)function create(proto) { function F() {}; F.prototype = proto; F.prototype.constructor = F;return new F();}五、实现bind方法核心要点:
1.对于普通函数,绑定this指向
2.对于构造函数,要保证原函数的原型对象上的属性不能丢失
Function.prototype.bind = function(context, ...args) { let self = this;//谨记this表示调用bind的函数 let fBound = function() { //this instanceof fBound为true表示构造函数的情况 。如new func.bind(obj) return self.apply(this instanceof fBound ? this : context || window, args); } fBound.prototype = Object.create(this.prototype);//保证原函数的原型对象上的属性不丢失 return fBound;}大家平时说的手写bind,其实就这么简单:)
六、实现new关键字核心要点:
- 创建一个全新的对象,这个对象的__proto__要指向构造函数的原型对象执行构造函数返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象
function myInstanceof(left, right) { let proto = Object.getPrototypeOf(left); while(true) { if(proto == null) return false; if(proto == right.prototype) return true; proto = Object.getPrototypeof(proto); }}八、实现单例模式核心要点: 用闭包和Proxy属性拦截
function proxy(func) { let instance; let handler = { constructor(target, args) { if(!instance) { instance = Reflect.constructor(fun, args); } return instance; } } return new Proxy(func, handler);}九、实现数组的flat方式其实很多,之前我做过系统整理,有六种方法,请参考:
JS数组扁平化(flat)方法总结[1]
十、实现防抖功能核心要点:
如果在定时器的时间范围内再次触发,则重新计时 。
const debounce = (fn, delay) => { let timer = null; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); };};十一、实现节流功能核心要点:
如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器 。
推荐阅读
- 油价下跌,再学会这些省油技巧,用车成本降一半
- 这些习惯容易影响肠胃健康,你有没有?越早改掉,肠胃越健康
- AT/CVT/DCT变速箱该怎么选?看完这些不再纠结
- 华为手机录屏没有声音,该如何解决?别急!试试这些方法
- iPhone越用越卡顿?不妨看看原因和这些解决方法
- 手机如何才能更省电?这些小技巧一定要知道
- 水果的这些“小秘密”,你都知道吗?
- 祛斑养颜茶这些茶多喝几杯你会更美
- Android面试题集锦之 Service
- 如果这些专业术语都搞不懂,你就不要在音响行业混了