资讯专栏INFORMATION COLUMN

如果再被问到原型和原型链......

muzhuyu / 2761人阅读

摘要:事后整理当时的思路如下简约版第一步是对象,对象都有原型也叫原型指针,指向构造函数的原型对象。第二步是构造函数,构造函数也是函数,函数除了有原型对象外,也有原型指针。第四步作为中的内建构造函数,同样拥有原型指针和原型对象。

前段时间求职过程中,经常会被问到关于原型和原型链,就问题本身而言并不难,主要是考察对JavaScript基本概念的理解,但如何能够说明白确实需要认真准备下。

我印象比较深刻的一次,有个面试官出了一道面试题,大意如下:

function Person(name) {
    this.name = name;
}

let person = new Person("yuyongyu");

请讲讲person和Object的关系,形式不限。

我当时下意识地脱口而出:Object在person的原型链上。当时从面试官复杂的表情可以推断出这不是他真正想要的答案,但我也基本可以断定他真实的意图就是想考察下对原型链的掌握,而且期望看到原型链的全貌。掌握了出题人的意图,那接下来就好办了。

事后整理当时的思路如下:

简约版
第一步:

person是对象,对象都有原型(也叫原型指针),指向构造函数的原型对象。

此处即person的__proto__属性指向Person的prototype。

注:__proto__最初是一个非标准属性,ES6已将其标准化,可以用标准方法Object.getPrototypeOf()替代,本文出于举例的直观性考虑,仍采用此属性。

第二步:

Person是构造函数,构造函数也是函数,函数除了有原型对象外,也有原型指针。

函数都是由Function构造出来的,故函数的原型指针指向Function的原型对象。

此处即Person的__proto__属性指向Function的prototype。

第三步:

Function是内建构造函数,内建构造函数也还是函数,除了有原型对象外,也有原型指针。

函数都是由Function构造出来的,Function作为函数,是由其自身构建出来,故Function的原型指针指向其自身的原型对象。

此处即Function的__proto__属性指向Function的prototype。

第四步:

Function的原型对象,其本身也是对象,故其原型指针指向Object的原型对象

此处即Function.prototype的__proto__属性指向Object的prototype。

为更加直观表示,作示意图如下:

以上为推导过程,必须代码验证,结果如下(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的原型对象也是对象,同样拥有构造器属性:constructor和原型指针。

函数的原型对象的构造器属性指向自身。

函数的原型对象的原型指针指向Object的原型对象

此处即Person.prototype的constructor属性指向Person;Person.prototype的__proto__属性指向Object的prototype。

第三步:

Function的原型对象和Person的原型对象一样,不再赘述。

此处即Function.prototype的constructor属性指向Function;Function.prototype的__proto__属性指向Object的prototype。

第四步:

Object作为JavaScript中的内建构造函数,同样拥有原型指针和原型对象。

Object既然是函数,故其原型指针指向Function的原型对象。

Object的原型对象同样包含构造器属性:constructor和原型指针。

Object的原型对象的构造器属性指向自身。

Object的原型对象的原型指针指向null。

此处即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的学习任重道远。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96151.html

相关文章

  • 记录一次杭州顺网科技的面试过程

    摘要:以上是面试中笔试涉及到的知识点或者后面被问到的只是点。也许是根据薪资和面试的等级来出题的。我刚面试完回家,吃了一个泡面,回忆下面试题。同时作为传递到构造函数,执行了一次让构造函数里面的属性和方法赋值了一份给。 css 如何水平垂直居中,请尽量多说几种方法?很尴尬,我多次面试都被问到这个问题,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...

    shiguibiao 评论0 收藏0
  • 记录一次杭州顺网科技的面试过程

    摘要:以上是面试中笔试涉及到的知识点或者后面被问到的只是点。也许是根据薪资和面试的等级来出题的。我刚面试完回家,吃了一个泡面,回忆下面试题。同时作为传递到构造函数,执行了一次让构造函数里面的属性和方法赋值了一份给。 css 如何水平垂直居中,请尽量多说几种方法?很尴尬,我多次面试都被问到这个问题,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...

    caiyongji 评论0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函数式编程前端掘金引言面向对象编程一直以来都是中的主导范式。函数式编程是一种强调减少对程序外部状态产生改变的方式。 JavaScript 函数式编程 - 前端 - 掘金引言 面向对象编程一直以来都是JavaScript中的主导范式。JavaScript作为一门多范式编程语言,然而,近几年,函数式编程越来越多得受到开发者的青睐。函数式编程是一种强调减少对程序外部状态产生改变的方式。因此,...

    cfanr 评论0 收藏0
  • 近期前端面试中经常碰到的问题总结

    摘要:手写深拷贝这个问题也是被问到了不止一遍,就连美团也问到了。个人能力有限,没能挺到美团的最后一轮面试,不过面试的几家公司也是涉及到了各行各业,这篇文章只是对即将面试的前端小伙伴们一个参考,最后效果还是要看个人努力的。 最近想着去市场中试试水,看看自己的几斤几两。哈哈,然后大概遇到了这么几类问题吧。写出来和大家分享一下。 原生类 1.原型及原型链的问题 这个问题面试的公司都有问。其实这...

    shadowbook 评论0 收藏0
  • 前端面试回顾(2)---类型检测

    摘要:运算符用来判断一个构造函数的属性所指向的对象是否存在另外一个要检测对象的原型链上。所以大多数时候它返回的都是一个对象的构造函数。想到了构造函数可能不一样,但说怎么判断就有点想不出词了,就持续懵逼中这篇内容参考了高级程序设计和一篇文章 一个经典的面试题 怎么去区分一个变量是一个数组还是一个对象呢? typeof 看到这个题目,可能首先就会typeof,typeof是最基本的数据类型判断方...

    fnngj 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<