原型 在前端面试当中属于考核 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__
描述 person
与 Person.prototype
的关系便是 person.__proto__ === Person.prototype
。
但是 __proto__
只是某些浏览器自身的实现并非是标准的方法,在实际的开发中我们应该使用 Object.getPrototypeOf()
方法来获取对象的原型。
小结
本篇文章为大家讲解了原型、原型链、prototype 和 __ proto__ 的相关知识,将上述内容整理为以下几点:
- [[Prototype]] 是对象的内置属性,它会指向其他的对象,我们将它所关联的对象称之为对象的原型,由 [[Prototype]] 串联起的链条称为原型链。
prototype
是函数拥有的属性,当我们将函数与new
关键词搭配,采用构造函数创建对象时,被创建对象的 [[Prototype]] 就会与函数的prototype
关联,成为实例对象的原型。__proto__
是对象拥有的属性,它是一个非标准的方法,但是通过它可以获得对象的原型。