上次发了一下手动实现Promise https://segmentfault.com/a/11... 以后有猿友问我私聊我其它的像bind, call这些有没有标准的写法。个人回答是没有,像这些api咱们只能仿照它的功能,只能作得很像很像,可是绝对标准的答案是没有的,就像我以前的那篇文章,也只是在参照PromiseA+规范去仿写。好多Promise特有的API和特性也没有写进去,由于个人目的是经过手写来让你们学习promise,如今的自动化构建工具及其插件这么多,功能这么强大咱们没有那么多的要求去为了实现兼容性而本身手动实现一遍。前端
包括我本身也是,面试的时候确实会问一些能不能手动实现一个什么什么的,可是这个目的并非招你过来手写API的,由于我认为手动造轮子或造框架要求你的js基本功必须扎实,想去实现一个东西,必需要完彻底全地了解它才能够。手动实现代码的过程当中每每也能看出一我的的编程思想。 固然,能写出来或者模拟地很像那确定是很是好的。react
这篇文章我建议你们不要刻意去收藏,去记从而去应付面试, 这样的学习方法不推荐(固然之前我也这样),这种文章读几遍就好了,最主要地是以后去看这些API的用法以及特色,以及发掘每一个人的编程思想, 而后本身写下来,甚至写的更好,记忆更加深入。而且我也建议你们项目中遇到问题以后,第一时间不要去想着 复制错误信息而后 百度一下,必应一下,google一下,这样意义不大,正确的作法我以为是先经过错误信息先本身找到错误根源,想想为何会出错,为何达不到你想要的结果,而后总结经验, 若是是一些框架API或者插件,遇到问题最好先去文档里面认真的看一下,而后学着本身手动解决。以前的我学新东西新技术很爱看视频,百度搜。可是如今的话我更愿意去看它的文档,有时间去逛它的社区,固然了, 新东西出来不要去盲目地学 学技术要本着一精多专的目的去学, 不过不管是什么方向, js的基础是很是很是重要的。面试
好了,废话太多了,进入正题。。。算法
这些API的特色以及具体用法我就不介绍了,相信你若是奔着手动实现的方向来看,那么你必定对它很了解编程
核心: this永远指向最后调用它的对象segmentfault
代码:api
Function.prototype.myCall = function(context, ...args) { context['key'] = this; context.key(...args); delete context.key; }
写到这里,call基本的特色已经实现,其实面试中通常写到这里也就经过了,可是实际上却还差很远。以前个人那篇文章也是如此,只是实现了基本的功能。由于完彻底全的实现确实会花费不少时间.
仍是简单说一下吧,咱们知道call中是能够传入一些基本类型的,而且咱们如今的这种实现方式增长了一个显示的key属性,实际上你在调用真正的call的时候去打印this是没法发现这些额外属性的,那么咱们就仿照这些特性再去优化,接近一下promise
Function.prototype.myCall = function(context, ...args) { let newContext = context; if ([null, undefined].includes(context) ) { newContext = window || {}; } switch (typeof context) { case 'number': { newContext = new Number(context); break; } case 'boolean': { newContext = new Boolean(context); break; } case 'string': { newContext = new String(context); break; } } Object.defineProperty(newContext, 'key', { value: this, configurable: true, enumerable: false, }); newContext.key(...args); delete newContext.key; }
这里就差很少了,后面的我就直接上代码了架构
Function.prototype.myApply = function(context, obj) { if (typeof obj !== 'object') { throw new TypeError('CreateListFromArrayLike called on non-object') } let newContext = context; if ([null, undefined].includes(context)) { newContext = window; } switch (typeof context) { case 'number': { newContext = new Number(context); break; } case 'boolean': { newContext = new Boolean(context); break; } case 'string': { newContext = new String(context); break; } } Object.defineProperty(newContext, 'key', { value: this, configurable: true, enumerable: false, }); newContext.key(...obj); delete newContext.key; };
Function.prototype.myBind = function(context, ...args) { let _this = this; let newFun = (...args2) => { _this.call(context, ...args, ...args2) }; newFun.prototype = Object.create(_this.prototype) return newFun };
https://segmentfault.com/a/11...app
Object.create = Object.create || function(obj){ var F = function(){}; F.prototype = obj; return new F(); }
function myNew(fun) { if (typeof fun !== 'function') throw new TypeError('fun is not a constructor') return function() { let obj = { '__proto__': fun.prototype } fun.call(obj, ...arguments) return obj } }
Array.prototype.myReduce = function(fn, orginal = '__orginal') { let copy = [...this] if (orginal !== '__orginal') { copy.unshift(orginal) } while (copy.length > 1) { let prev = copy.shift() let next = copy.shift() copy.unshift(fn(prev, next)) } return copy[0] }
仍是以前那句话,这些东西不推荐去硬记(若是你为了应付面试当我没说),目的是掌握它而后可以本身写下来。最后再说一下,虽然咱们如今都是站在巨人的肩旁上,不少东西咱们拿来即用就能够,可是是否还要有这种需求呢?有,固然有,任何东西都不是绝对完美的,react好用,可是你知道setState到底应该同步仍是异步的口水大战吗? 完美是由于适应,你能手写是由于我知道你绝对理解,好多公司有本身的框架,也都是会借鉴,仿写甚至在源码的基础上去优化成为适应自身公司业务的框架。你想一想,对API的核心原理以及用法都不理解,不知道JS线程与GUI渲染线程互斥,不理解模块化的意义, 不知道设计原则,不清楚何为设计何为模式,你又怎么进阶到手写源码,架构底层或是对前端性能进行优化呢? 因此,不要着急去背,哪里不会哪里没有理解就认真地去理解它。接下来我应该会发一系列的算法文章,若是有兴趣的能够提早关注一下, 固然了,若是你以为对你有帮助, 麻烦点个赞,若是以为哪里写的不严谨麻烦指出,共勉!