JavaScript深入之从原型到原型链(笔记)

221 阅读2分钟

读大佬 @冴羽 JavaScript深入系列juejin.cn/post/684490… 有感

1511760169801232.jpg

prototype

每个函数都有一个 prototype 属性, prototype是函数才会有的属性:

function Person() {

}
console.log(Person.prototype)  // {constructor: ƒ Person(), [[Prototype]]: Object}
// Object函数
// console.log(Object.prototype)

那这个函数的 prototype 属性到底指向的是什么呢?

console.log(typeof Person.prototype)  // object

通过打印可知,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型(实例原型)。 用图表示: image.png 实例:实例是类的具象化产品。比如:

  • 类:比如 人类
  • 实例:比如 王小二 那么,王小二的父母孕育他直到出生的过程,就叫:实例化
function Human(name){
    this.name = name;
}
var wangxiaoer = new Human('王小二'); //这一步叫作 实例化

原型:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。new Person(),就是Person的原型。

__proto__

每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。 函数的实例有个__proto__属性,函数自身有个prototype属性,这两者是相等的。 如图: image.png

function Person() {

}
var a = new Person().__proto__
console.log(a)  // {constructor: ƒ Person(), [[Prototype]]: Object}
var b = Person.prototype 
console.log(b) // {constructor: ƒ Person(), [[Prototype]]: Object}
a===b  // true

constructor

每个原型都有一个 constructor 属性指向关联的构造函数。 如图: image.png

function Person() {

}
console.log(Person)  // ƒ Person() {}
console.log(Person.prototype.constructor)  // ƒ Person() {}
Person === Person.prototype.constructor   // true
// 获取对象的原型的方法
var a = Object.getPrototypeOf(new Person())  // {constructor: ƒ Person(), [[Prototype]]: Object}
// 可知
console.log(a===Person.prototype)  // true
console.log(a===new Person().__proto__)   // true

实例与原型

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。

var c = [22,33]
console.log(c.indexOf())  // -1
// 肉眼可见c没有indexOf的属性,但是c.indexOf却没有报错,说明indexOf在c的原型里面。
// 那么c的原型c.__proto__, 打印c.__proto__可知,indexOf就是其属性。
// 打印Array.prototype可知,其也有indexOf属性,那么
console.log(Array.prototype === c.__proto__)   // true

原型的原型以及原型链

接着上面来,那么Array.prototype的原型是: 通过打印c.__proto__.__proto__或者Array.prototype.__proto__可知,Array.prototype的原型就是Object.prototype。而Object.prototype的原型就是null了,如图:

image.png 图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。

补充

__proto__ ,绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)。

Object.create(null),可创造一个属于自己的原型链,详情可见juejin.cn/post/684490…