前段时间求职过程当中,常常会被问到关于原型和原型链,就问题自己而言并不难,主要是考察对JavaScript基本概念的理解,但如何可以说明白确实须要认真准备下。node
我印象比较深入的一次,有个面试官出了一道面试题,大意以下:面试
function Person(name) { this.name = name; } let person = new Person('yuyongyu');
请讲讲person和Object的关系,形式不限。函数
我当时下意识地脱口而出:Object在person的原型链上。当时从面试官复杂的表情能够推断出这不是他真正想要的答案,但我也基本能够判定他真实的意图就是想考察下对原型链的掌握,并且指望看到原型链的全貌。掌握了出题人的意图,那接下来就好办了。学习
过后整理当时的思路以下:this
此处即person的__proto__属性指向Person的prototype。spa
注:__proto__最初是一个非标准属性,ES6已将其标准化,能够用标准方法Object.getPrototypeOf()替代,本文出于举例的直观性考虑,仍采用此属性。prototype
此处即Person的__proto__属性指向Function的prototype。设计
此处即Function的__proto__属性指向Function的prototype。指针
此处即Function.prototype的__proto__属性指向Object的prototype。code
为更加直观表示,做示意图以下:
以上为推导过程,必须代码验证,结果以下(node环境,ES6版):
function Person(name) { this.name = name; } let person = new Person('yuyongyu'); //第一步验证 console.log(person.__proto__ === Person.prototype); // true //第二步验证 console.log(Person.__proto__ === Function.prototype); // true //第三步验证 console.log(Function.__proto__ === Function.prototype); // true //第四步验证 console.log(Function.prototype.__proto__ === Object.prototype); // true
至此基本达到了面试官的要求,但过后思考,整个过程过于简略,还能够进一步扩展,丰富整个过程。过后扩展思路以下:
此处即Person.prototype的constructor属性指向Person;Person.prototype的__proto__属性指向Object的prototype。
此处即Function.prototype的constructor属性指向Function;Function.prototype的__proto__属性指向Object的prototype。
此处即Object的__proto__属性指向Function的prototype;Object.prototype的constructor属性指向Object;Object.prototype的__proto__属性指向null.
示意图以下(虚线仅表明不交叉,无特殊含义):
代码验证结果以下:
function Person(name) { this.name = name; } let person = new Person('yuyongyu'); //第一步验证 console.log(person.__proto__ === Person.prototype); // true console.log(person.constructor === Person); // true //第二步验证 console.log(Person.__proto__ === Function.prototype); // true console.log(Person.prototype.constructor === Person); // true console.log(Person.prototype.__proto__ === Object.prototype);// true //第三步验证 console.log(Function.__proto__ === Function.prototype); // true console.log(Function.prototype.constructor === Function); console.log(Function.prototype.__proto__ === Object.prototype); //第四步验证 console.log(Object.__proto__ === Function.prototype); // true console.log(Object.prototype.constructor === Object); // true console.log(Object.prototype.__proto__ === null); // true
注意到上图中那个红色的null了吗?
JavaScript到处皆对象,而原型链的尽头居然是null,不禁到想到一句佛语:万物皆空。
若是从反向来看,是null衍生出了丰富多彩的JavaScript世界,不禁得又想到了一句道语:一辈子二,二生三,三生万物
另外,由上图可知Object.__proto__ === Function.prototype,Function.prototype.__proto__ === Object.prototype,即Object做为内建函数由Function构造出来,Function做为内建构造函数又是对象(函数都是对象),这彷佛又进入了“鸡生蛋和蛋生鸡”的哲学范畴。
因而可知JavaScript的设计思想可谓博大精深,难免感慨JavaScript的学习任重道远。