读大佬 @冴羽 JavaScript深入系列juejin.cn/post/684490… 有感
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 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型(实例原型)。
用图表示:
实例:实例是类的具象化产品。比如:
- 类:比如 人类
- 实例:比如 王小二 那么,王小二的父母孕育他直到出生的过程,就叫:实例化
function Human(name){
this.name = name;
}
var wangxiaoer = new Human('王小二'); //这一步叫作 实例化
原型:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。new Person(),就是Person的原型。
__proto__
每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。
函数的实例有个__proto__属性,函数自身有个prototype属性,这两者是相等的。
如图:
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 属性指向关联的构造函数。
如图:
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了,如图:
图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。
补充
__proto__ ,绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,可以理解成返回了 Object.getPrototypeOf(obj)。
Object.create(null),可创造一个属于自己的原型链,详情可见juejin.cn/post/684490…