有一位小明同学(指代构造函数),他有自己的朋友圈子(指代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); // => trueproto 指向构造当前对象的构造函数的prototype,由于万物皆对象,对象又是通过构造函数构造而来。故Function通过Function构造而来,所以指向了Function.prototype
console.log(Function.__proto__ === Function.prototype); // => true有兴趣的朋友可以再看看这篇文章
然后,我们再来看看这张图,跟着箭头走一遍,是不是就很清晰了?
继续generator包装mark方法会指定genFun的__proto__和prototype,完完全全替换了genFun的朋友圈以及创造genFun的构造函数的朋友圈,现在genFun就是Generator的克隆品了。
用来设置__proto__ 和 prototype的值,GeneratorFunctionPrototype,GP,我们也简单过一下:
// 创建polyfill对象 var IteratorPrototype = {}; IteratorPrototype[iteratorSymbol] = function () { return this; }; // 原型相关操作 // 获取对象的原型: __proto__ var getProto = Object.getPrototypeOf; // 原生iterator原型 var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); // IteratorPrototype设置为原生 if ( NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) ) { // This environment has a native %IteratorPrototype%; use it instead // of the polyfill. IteratorPrototype = NativeIteratorPrototype; } // 创造原型 // Gp 为 迭代器原型 // IteratorPrototype作为原型对象 var Gp = (GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create( IteratorPrototype )); // 更新构造函数和原型 GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; GeneratorFunctionPrototype.constructor = GeneratorFunction; // toString,调用Object.toString.call的时候会返回GeneratorFunction GeneratorFunctionPrototype[ toStringTagSymbol ] = GeneratorFunction.displayName = 'GeneratorFunction';最后再返回经过处理的genFun,然后再回到mark函数外~
_asyncToGenerator_asyncToGenerator 接收mark处理过的结果:
// fn 为 generator 的克隆品 function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { // 调用_callee,先看下面,一会在回来哈~ var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep( gen, resolve, reject, _next, _throw, 'next', value ); } function _throw(err) { asyncGeneratorStep( gen, resolve, reject, _next, _throw, 'throw', err ); } _next(undefined); }); }; } regeneratorRuntime.wrap