前端面试之JavaScript基础(一)—— 原型

639 阅读2分钟

原型 在前端面试当中属于考核 JavaScript 基础功底的高频考点,但是我相信还有许多人不清楚原型是什么,更对 prototype__proto__ 傻傻分不清楚。别担心,接下来我将为大家解决这些困惑。

[[Prototype]]

在 JavaScript 中对象拥有一个特殊的属性 [[Prototype]],这个特殊的属性是对其他对象的引用,为了更好的接受这个概念,我将 [[Prototype]] 所引用的对象理解为本对象的原型,对象总能从原型上"继承"属性,举个例子:

var anotherObject = {
  name: 'O_c',
}

var myObject = Object.create(anotherObject)

myObject.name // O_c

上述例子中 myObject 对象的 [[Prototype]] 属性引用了 anotherObject 对象,我们就能理解为 myObject 对象的"原型"指向 anotherObject对象,并从 anotherObject 对象上"继承"了 name 属性。

几乎所有的对象 在创建时 [[Prototype]] 属性都会被赋予非空的值,由 [[Prototype]] 串联起来的对象的关联链条我们就称为 [[Prototype]]链(原型链),一般情况下 [[Prototype]] 链的最顶层是 Object.prototype 对象。

prototype

prototype 实际上是所有 函数 都拥有的属性(enumerable为false),重!点!强!调! prototype 是与函数相关的概念。为了更透彻的了解 prototype 我们先来看一段经常见到的代码片段:

function Person {
  ...
}

Person.prototype.name = 'O_c'

var person = new Person();

person.name // O_c

这段代码中我们通过 Person 构造函数创建出 person 对象,但是并没有为 person 对象创建名为 name 的属性,那为什么在访问 person.name 仍然能获得结果呢?

理由很简单,当我们用 new 关键字创建 person 对象时,person 对象的 [[Prototype]] 属性会引用 Person.prototype 指向的对象。

Person.prototype 事实上就是所有通过 Person 构造函数创建的实例的原型。普通的对象的原型即是 Object.prototype

__ proto __

__proto__ 是一种非标准的方法,对象可以通过 __proto__ 访问内部的 [[Prototype]] 属性,既我们可以通过 __proto__ 访问对象的原型,它是一个与 对象 相关的概念。

如果用 __proto__ 描述 personPerson.prototype 的关系便是 person.__proto__ === Person.prototype

但是 __proto__ 只是某些浏览器自身的实现并非是标准的方法,在实际的开发中我们应该使用 Object.getPrototypeOf() 方法来获取对象的原型。

小结

本篇文章为大家讲解了原型、原型链、prototype 和 __ proto__ 的相关知识,将上述内容整理为以下几点:

  • [[Prototype]] 是对象的内置属性,它会指向其他的对象,我们将它所关联的对象称之为对象的原型,由 [[Prototype]] 串联起的链条称为原型链。
  • prototype 是函数拥有的属性,当我们将函数与 new 关键词搭配,采用构造函数创建对象时,被创建对象的 [[Prototype]] 就会与函数的 prototype 关联,成为实例对象的原型。
  • __proto__ 是对象拥有的属性,它是一个非标准的方法,但是通过它可以获得对象的原型。