面试题:说说 proto 和 prototype

286 阅读2分钟

一、介绍

在开始讲之前,先跟大家提出两个概念:

  • __proto__,隐式原型
  • prototype,显示原型

proto

在类似 java 这种语言中,继承的概念是通过类和类之间实现的,但 javascript 根本没有类,都是对象

所以在 javaScript中,继承的概念是通过对象和对象之间实现的,而__proto__就是作为两个对象连接的纽带,以此确定继承关系

var A = {name:'前端收割机'}
var B = {age:18}
var c = {hobby:'摄影'}

A.__proto__ = B;//将B设置为A的父对象
B.__proto__ = C;//将C设置为B的父对象

console.log(A.name) //前端收割机
console.log(A.age)  //18
console.log(A.hobby)//摄影

从上面可以看到,

  • 对象 A的__proto__属性指向的那个对象B,即B就是 A 的原型对象(或者叫父对象),对象 A 可以使用对象 B 中的属性和方法
  • 对象 B的__proto__属性指向的那个对象C,即C就是 B 的原型对象(或者叫父对象),对象 A 可以使用对象 C 中的属性和方法

以此递归,就是所谓的原型链

prototype

回顾一下new的作用:

  • 创建一个实例对象

  • 把实例对象的__proto__属性指向构造函数的prototype

  • this绑定到实例上,然后再执行函数体

下面来看一张图:

从上图我们可以找出foo对象和Foo函数的原型链:

foo对象原型链

foo.__proto__ == Foo.prototype;
foo.__proto__.__proto__ == Foo.prototype.__proto__ == Object.prototype;
foo.__proto__.__proto__.__proto__ == Foo.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;

Foo构造函数原型链

Foo.__proto__ == Function.prototype;
Foo.__proto__.__proto__ == Function.prototype.__proto__;
Foo.__proto__.__proto__.__proto__ == Function.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;

构造函数Foo的原型链上没有Foo.prototype,因此无法继承Foo.prototype上的属性和方法。而实例foo的原型链上有Foo.prototype,因此foo可以继承Foo.prototype上的属性和方法。

二、区别

  • __proto__(和constructor属性)是对象所独有的

  • prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__constructor属性

三、作用

__ proto__:

  • 实现对象之间的继承,形成原型链

  • 使子辈对象可以使用父辈的属性和方法

prototype:

  • 让该构造函数所实例化的对象们都可以找到公用的属性和方法( 即 foo.__proto__ === Foo.prototype )
  • 使Javascript借助 prototype属性来模仿实现类和类之间的继承模式

四、结束语

如果觉得这篇文章对你有帮助,可以伸出你的小手,为这篇文章点个赞

我是前端路上一位新晋的萌新,怀着学习的态度,怀着认识各位同伴的心态,把自己的知识分享出来,除了让自己对知识认知更加巩固,也希望大家能够通过我写的文章学到一点微薄的知识,如果知识内容有误,可以在评论区或者下面公众号告诉我,我会立刻更改

最后,我也创建了一个 【前端收割机】的公众号,希望大家可以关注一波,里面的文章都是掉头发之作