一道有趣的面试题

协变潮涌
• 阅读 1153
function yideng(){}
const a = {}, b = Object.prototype;
console.log(a.prototype === b);
console.log(Object.getPrototypeOf(a) === b);
console.log(yideng.prototype === Object.getPrototypeOf(yideng));
//写出执行结果

一道有趣的面试题

答案:false true false

//知识点
__proto__(隐式原型)与prototype(显式原型)
1)是什么?
①显式原型 explicit prototype property:
每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象。(需要注意的是,通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性)
②隐式原型 implicit prototype link:
JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf()。(注意:Object.prototype 这个对象是个例外,它的__proto__值为null)
③二者的关系:
隐式原型指向创建这个对象的函数(constructor)的prototype

2)作用是什么?
①显式原型的作用:用来实现基于原型的继承与属性的共享。
②隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着__proto__依次查找。

3)__proto__的指向:
__proto__的指向到底如何判断呢?根据ECMA定义 'to the value of its constructor’s "prototype" ' ----指向创建这个对象的函数的显式原型。
所以关键的点在于找到创建这个对象的构造函数,接下来就来看一下JS中对象被创建的方式,一眼看过去似乎有三种方式:(1)对象字面量的方式 (2)new 的方式 (3)ES5中的Object.create()。
但是本质上只有一种方式,也就是通过new来创建。为什么这么说呢,首先字面量的方式是一种为了开发人员更方便创建对象的一个语法糖,本质就是 var o = new Object(); o.xx = xx;o.yy=yy;

//解析:

1)a.prototype === b =>false
prototype属性是只有函数才特有的属性,当你创建一个函数时,js会自动为这个函数加上prototype属性,值是一个空对象。而实例对象是没有prototype属性的。所以a.prototype是undefined,第一个结果为false。

2)Object.getPrototypeOf(a) === b =>true
首先要明确对象和构造函数的关系,对象在创建的时候,其__proto__会指向其构造函数的prototype属性
Object实际上是一个构造函数(typeof Object的结果为"function"),使用字面量创建对象和new Object创建对象是一样的,所以a.__proto__也就是Object.prototype,所以Object.getPrototypeOf(a)与a.__proto__是一样的,第二个结果为true

3)yideng.prototype === Object.getPrototypeOf(yideng) =>false
关键点:f.prototype和Object.getPrototypeOf(f)说的不是一回事

①f.prototype 是使用使用 new 创建的 f 实例的原型:
f.prototype === Object.getPrototypeOf(new f()); // true

②Object.getPrototypeOf(f)是 f 函数的原型:
Object.getPrototypeOf(f) === Function.prototype; //true

所以答案是 false

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
ZY ZY
4年前
js堆和栈
浅析js中堆内存和栈内存我们常遇见的varletconst区别cont定义的基本类型不能改变,但是定义的对象是可以通过修改对象属性等方法来改变的consta1;console.log(a)//a;cosnole.log(a2)//报错constb;b.name1;console.log(b)//name:1con
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
小嫌 小嫌
3年前
js中箭头函数在对象内部的继承
function函数functionPerson()this.name'Jack',this.age25,this.sayNamefunction()console.log(this.name)functioninner()console.log(this.n
小嫌 小嫌
3年前
Javascript中的变量提升
定义JavaScript中奇怪的一点是你可以在变量和函数声明之前使用它们。就好像是变量声明和函数声明被提升了代码的顶部一样。sayHi()//Hithere!functionsayHi()console.log('Hithere!')name'JohnDoe'console.log(name)//JohnDoevarn
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
LinMeng LinMeng
4年前
vue的watch监听
vue的watch监听函数watch用来响应数据的变化,watch的用法大致有以下三种:1.监听某个变量watch:{name(newName,oldName){console.log(newName)//改变前的值console.log(oldName)//改变后的值
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
3年前
Babel编译:类继承
编译前//父类classFruit{staticnutrition"vitamin"staticplant(){console.log('种果树');}name;constructor(name){
可莉 可莉
3年前
18 个 JavaScript 入门技巧!(含2020JavaScript面试题整理)
1\.转字符串constinput123;console.log(input'');//'123'console.log(String(input));//'123'console.log(input.toString());//'123'