原型和原型链是什么?他很难吗?很难理解吗

499 阅读5分钟

原型和原型链是 javascript 的基础, 同时也是面试中的一个高频考题,看似一道最基础送分题,但是如果回答的不好可能就变成了送命题。小黄就从四个面试题从如下四个方面展开介绍吧,看不懂来砍我就行: 图片描述

二、什么是原型和原型链?

  • 什么是原型?
    在 javascript 中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype), 正如下面所展示
function persion() {}
console.log(persion.prototype);

在浏览器中运行这段代码之后可以清楚的看到我们的原型对象:

图片描述

三、什么是原型链?

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。 —如上内容摘自 MDN

简单理解:
原型链就是当我们访问对象的某个属性或方法时,如果在当前对象中找不到定义,会继续在当前对象的原型对象中查找,如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型)如此继续,直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回
undefined。可以看出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链。拥有相同原型的多个对象,他们的共同特征正是通过这种查找模式体现出来的。

这在上面的查找过程,我们提到了最顶层的原型对象, 这个对象就是 Object.prototype,这个对象中保存了最常用的方法,如 toString、valueOf、hasOwnProperty 等,因此我们才能在任何对象中使用这些方法。

下面我们通过代码来直观的理解下:

const persion = { name: 'zhangsan', age: 20 };
console.log(persion.toString);

这段代码在浏览器中运行之后可以看到如下的输出:

ƒ toString() { [native code] }

这地方我们会有个疑问就是说, 我们的 persion 对象并没有定义 toString 属性, 为什么当我们访问 toString 的时候可以拿到结果呢?我们继续在浏览器中执行如下代码:

const persion = { name: 'zhangsan', age: 20 };
console.log(persion);

这段代码在浏览器中运行之后可以看到如下的输出:
图片描述

通过如上输出我们可以看到我们拿到的 persion.toString, 其实是定义在 persion.proto也就是我们 persion 对象的原型中的。当我们访问 persion.toString 的时候在 persion 对象本身没找到所以就去 persion.proto中找, 最终找到了我们想要的 toString 方法。这就是通过原型链访问对象属性的一个实际例子。

四、原型和原型链存在的意义是什么?

了解了原型和原型链的概念之后, 我们来思考下, 原型和原型链存在的意义是什么? 带着这个问题我们来看下面代码:

// 初始化构造函数
function Monkey(name, age) {
  this.name = name;
  this.age = age;
}
Monkey.prototype.from = 'zoo';
// 实例化wukong对象
let WuKong = new Monkey('WuKong', 800);
console.log(WuKong);

打印 wukong, 他有自己属性 name = ‘WuKong’, age = 800; 同时通过原型链关系,他有属性 from = ‘zoo’;

我们再创建实例 LiuEr

// 实例化LiuEr对象
let LiuEr = new Monkey('LiuEr', 600);
console.log(LiuEr);

打印 LiuEr, 他有自己属性 name = ‘LiuEr’,age = 600; 同时通过原型链关系,他有属性 from = ‘zoo’;可以看出原型对象存放了 WuKong、LiuEr 共有的属性 from = ‘zoo’. from 属性,而是将这一属性存在他们的构造函数原型对象上,对于 Monkey 这样的构造函数。相同的属性、方法还有很多很多,比如都喜欢吃香蕉,都需要睡觉,当相同的属性、方法越多,原型、原型链的意义越大。这是就是原型、原型链的意义所在!实例对象可以共享构造函数原型属性和方法, 节省内存。构造函数原型上的属性和方法越多,节省内存越大。

五、面试官主要考察什么?

  • js 基础是否扎实?
    能否清晰的回答出原型和原型链的概念
  • 针对原型和原型链是否有自己的理解?
    是否思考过,原型和原型链存在的意义是什么。

六、面试中遇到该题目我们该如何回答?

讲清楚如下两个点:

  • 什么是原型和原型链?
    什么是原型
    在 javascript 中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)
    什么是原型链
    原型链就是当我们访问对象的某个属性或方法时,如果在当前对象中找不到定义,会继续在当前对象的原型对象中查找,如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型)如此继续,直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回 undefined。可以看出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链
  • 原型和原型链存在的意义是什么?
    使得实例对象可以共享构造函数原型属性和方法, 节省内存。构造函数原型上的属性和方法越多,节省内存越大.