原型:构造函数天生自带的一个prototype 为构造函数添加方法,专门给实例对象使用
四个规则
- 引用类型,都具有对象特性,即可自由扩展属性。
- 引用类型,都有一个隐式原型 proto 属性,属性值是一个普通的对象。
- 引用类型,隐式原型 proto 的属性值指向它的构造函数的显式原型 prototype 属性值。
- 当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 proto(也就是它的构造函数的显式原型 prototype)中寻找。
规则一
引用类型,都具有对象特性,即可自由扩展属性:
const obj = {}
const arr = []
const fn = function () {}
obj.a = 1
arr.a = 1
fn.a = 1
console.log(obj.a) // 1
console.log(arr.a) // 1
console.log(fn.a) // 1
规则二
引用类型,都有一个隐式原型 proto 属性,属性值是一个普通的对象:
const obj = {};
const arr = [];
const fn = function() {}
console.log('obj.__proto__', obj.__proto__);
console.log('arr.__proto__', arr.__proto__);
console.log('fn.__proto__', fn.__proto__);
规则三
引用类型,隐式原型 proto 的属性值指向它的构造函数的显式原型 prototype 属性值:
const obj = {};
const arr = [];
const fn = function() {}
obj.__proto__ == Object.prototype // true
arr.__proto__ === Array.prototype // true
fn.__proto__ == Function.prototype // true
规则四
当你试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的隐式原型 proto(也就是它的构造函数的显式原型 prototype)中寻找:
const obj = { a:1 }
obj.toString
// ƒ toString() { [native code] }
首先, obj 对象并没有 toString 属性,之所以能获取到 toString 属性,是遵循了第四条规则,从它的构造函数 Object 的 prototype 里去获取。
原型链
用 proto 串联起来的对象链状结构 注意: 使用 proto 每一个对象数据类型, 都有一个属于自己的原型链 作用: 为了访问对象成员
7个问题引出原型链
- 实例对象身上的 proto 指向谁?
- 指向所属构造函数的 prototype
- p1 所属的构造函数是 Person
- p1.proto 指向 Person.prototype
- Person.prototype 的 proto 指向谁 ?
- Person.prototype 所属的构造函数是谁
- 因为 Perosn.prototype 是一个对象数据类型(Object)
- 在 JS 内所有的 Object 数据类型都是属于 Object 这个内置构造函数
- Person.prototype 是属于 Object 这个内置构造函数的
- Person.prototype 的 proto 指向 Object.prototype
- Person 的 proto 指向谁 ?
- Person 是一个函数, 函数本身也是一个对象, 就会有 proto
- 在 JS 内, 所有的函数都是属于内置构造函数 Function 的实例
- Person.proto 指向 Function.prototype
- Object.prototype 的 proto 指向谁 ?
- Object.prototype 是一个对象数据类型, 只要是对象, 都是数据 Object 这个内置构造函数的
- 注意: Object.prototype 在 JS 内叫做顶级原型, 不在有 proto 了
- Object.prototype 的 proto 指向 null
- Object 的 proto 指向谁 ?
- Object 是内一个内置构造函数, 同时也是一个函数, 同时也是一个对象
- 在 JS 内, 所以的函数都是属于内置构造函数 Function 的实例
- Object 也是 Function 的实例
- Object.proto 指向 Function.prototype
- Function.prototype 的 proto 指向谁 ?
- Function.prototype 也是一个对象数据类型
- 只要是对象数据类型都是 Object 的实例
- Function.prototype 的 proto 指向 Object.prototype
- Function 的 proto 指向谁 ?
- Function 也是一个内置构造函数, 也是一个函数
- 在 JS 内, 所有的函数都是属于内置构造函数 Function 的实例
- Function 自己是自己的构造函数
- Function 自己是自己的实例对象
- Function 所属的构造函数的是 Function
对象访问机制
- 当你需要访问对象的成员的时候
- 首先在自己身上查找, 如果有直接使用
- 如果没有, 会自动去 proto 上查找
- 如果还没有, 就再去 proto 上查找
- 直到 Object.prototype 都没有, 那么返回 undefined
总结
原型链就是一个过程,原型是原型链这个过程中的一个单位,贯穿整个原型链。就好像你要是看完了不点个赞,我可以顺着网线找到你。