大家好,我是小雨小雨,致力于分享有趣的、实用的技术文章。
内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步。
分享不易,希望能够得到大家的支持和关注。
前言
async & await 和我们的日常开发紧密相连,但是你真的了解其背后的原理吗?
本文假设你对promise、generator有一定了解。
generator包装
fn内部调用的是_fn,一个私有方法,使用的apply绑定的this,并传入了动态参数。
_fn内调用了_asyncToGenerator方法,由于js调用栈后进先出:
读起来是这样的:fn() => _asyncToGenerator => .mark()
执行是反过来的:.mark() => _asyncToGenerator => fn()
我们先往里看,映入眼帘的是regeneratorRuntime.mark,该方法是generator的polyfill暴露的方法之一,我们去内部(require('regenerator-runtime/runtime'))简单看下这个mark是用来干什么的。
// 立即执行函数,适配commonjs和浏览器
(function (exports) {
// 暴露mark方法
exports.mark = function (genFun) {
// 兼容判断__proto__,处理老旧环境
if (Object.setPrototypeOf) {
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
} else {
genFun.__proto__ = GeneratorFunctionPrototype;
// 设置Symbol.toStringTag,适配toString
if (!(toStringTagSymbol in genFun)) {
genFun[toStringTagSymbol] = 'GeneratorFunction';
}
}
// 设置原型
genFun.prototype = Object.create(Gp);
return genFun;
};
})(typeof module === 'Object' ? module.exports : {});
mark做了两个操作,一个是设置genFun的__proto__,一个是设置prototype,可能有人会好奇:
__proto__不是对象上的吗?prototype不是函数上的吗?为啥两个同时应用到一个上面了
这样操作是没问题的,genFun不仅是函数啊,函数还是对象,js中万物皆对象哦。你想想是不是可以通过Function构造函数new出一个函数?
然后开始设置__proto__和prototype,在次之前,我们来简单捋一下原型。
原型
下面是个人理解的一个说法,未查阅v8引擎,但是这样是说得通的。如果有问题,欢迎指出,一起沟通,我也会及时修改,以免误导他人!!!。
首先要知道这三个的概念:搞清对象的原型对象(proto)、构造函数的原型(prototype)、构造方法(constructor)。
方便记忆,只需要记住下面几条即可:
- prototype是构造函数(注意:构造函数也是对象嗷)上特有的属性,代表构造函数的原型。举个例子:
有一位小明同学(指代构造函数),他有自己的朋友圈子(指代prototype),通过小明可以找到小红(构造函数.prototype.小红),在通过小红的朋友圈子(prototype)还能找到小蓝,直到有一个人(指代null),孑然一身、无欲无求,莫得朋友。
上面这个关系链就可以理解为原型链。
- __proto__是每一个对象上特有的属性,指向当前对象构造函数的prototype。再举个例子:
小明家里催的急,不就就生了个大胖小子(通过构造函数{小明}创造出对象{大胖小子}),可以说这个大胖小子一出生就被众星捧月,小明的朋友们纷纷表示,以后孩子有啥事需要帮忙找我就成。这就指代对象上的__proto__,__proto__可以引用构造函数的任何关系。
所以说,代码源于生活~
-
constructor是啥呢,就是一个prototype上的属性,表示这个朋友圈子是谁的,对于小明来说: 小明.prototype.constructor === 小明。所以,当我们进行继成操作的时候,有必要修正一下constructor,不然朋友圈子就乱了~
-
js中函数和对象有点套娃的意思,万物皆对象,对象又是从构造函数构造而来。对于小明来说,就是我生我生我~~
来看两个判断:
proto 指向构造当前对象的构造函数的prototype,由于万物皆对象,对象又是通过构造函数构造而来。故Object通过Function构造而来,所以指向了Function.prototype
console.log(Object.__proto__ === Function.prototype); // => true
proto 指向构造当前对象的构造函数的prototype,由于万物皆对象,对象又是通过构造函数构造而来。故Function通过Function构造而来,所以指向了Function.prototype
console.log(Function.__proto__ === Function.prototype); // => true
有兴趣的朋友可以再看看这篇文章
然后,我们再来看看这张图,跟着箭头走一遍,是不是就很清晰了?