原型和原型链
一直以来,对于原型和原型链一直都是处于明白但是讲不清楚地情况,所以准备写篇博客梳理下
在使用JavaScript这门语言时,我们经常会看到构造函数,原型、原型链、prototype、__proto__ 等等词汇,对于有些新手JavaScript开发者会感觉很疑惑。
JavaScript是一门面向对象的语言,但是在es6的class出来之前,我们一直都是用构造函数来实例化对象。
function Cat() {
this.color = 'orange'
}
var cat = new Cat()
console.log(cat.color) // orange
prototype
每个函数都有一个prototype属性,它的值是一个对象
function Cat() {
this.color = 'orange'
}
console.log(Cat.prototype)
控制台打印

__proto__
在 JavaScript 中,每个实例对象都有一个私有属性 [[Prototype]],该属性指向了这个实例对象的原型,你可以通过 ES6 的 Object.getPrototypeOf() 来访问该属性,许多浏览器也对 [[Prototype]] 进行了实现,也就是我们经常见到的 __proto__,__proto__ 指向了实例对象的原型,它也是一个对象。
function Cat() { this.color = 'orange' } var cat = new Cat() console.log(cat.__proto__) console.log(Object.getPrototypeOf(cat) === cat.__proto__) // true
控制台打印

实例对象的 __proto__ 与创建该实例对象的构造函数的 prototype 是相等的,构造函数的 prototype 指向调用该构造函数而创建的实例对象的原型
function Cat() { this.color = 'orange' } var cat = new Cat() console.log(cat.__proto__ === Cat.prototype) // true
对于构造函数的 prototype 和实例对象的 __proto__ 的关系,我们用张图来展示下

constructor
每个原型对象都有一个 constructor 属性,指向相关联的构造函数,所以构造函数和构造函数的 prototype 是可以相互指向的。实例对象也可以访问constructor 属性指向其构造函数。

原型链
function Cat() { this.color = 'orange' } Cat.prototype.age = 4 var cat = new Cat() console.log(cat.color) // orange console.log(cat.age) // 4
在构造函数中,我并没有设置有关 age 的属性,只是把 age 设置在了实例原型上,然后我们通过实例对象也能访问到 age 属性。在 JavaScript 中,如果想访问某个属性,首先会在实例对象(cat)的内部寻找,如果没找到,就会在该对象的原型(cat.__proto__,即 Cat.prototype)上找,我们知道,对象的原型也是对象,它也有原型,如果在对象的原型上也没有找到目标属性,则会在对象的原型的原型(Cat.prototype.__proto__)上寻找,以此内推,直到找到这个属性或者到达了最顶层。在原型上一层一层寻找,这便就是原型链了。
实例对象原型的原型是Object.prototype,而它的原型是null,null 没有原型,所以 Object.prototype 就是原型链的最顶端。
function Cat() { this.color = 'orange' } console.log(Cat.prototype.__ptoto__ === Object.prototype) // true console.log(Object.prototype.__proto__) // null
JavaScript 中的所有对象都来自 Object,Object 位于原型链的最顶端,几乎所有 JavaScript 的实例对象都是基于 Object。

继承
javaScript 的继承是基于原型链的,在原型链的任何位置设置属性,都能被对象访问到,原型的作用也是在此,它可以包含所有实例共享的属性和方法,就像该属性本来就在实例对象上一样。
function Cat() { this.color = 'orange' this.age = 4 } Cat.prototype.getColor = function() { console.log(this.color) } Object.prototype.getAge = function() { console.log(this.age) } var cat = new Cat() cat.getColor() // orange cat.getAge() var a = ['hello', 'world'] function f() {} console.log(a.__proto__ === Array.prototype) // true console.log(f.__proto__ === Function.prototype) // true

浙公网安备 33010602011771号