原型 和 原型链
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。看完事件的相关内容,写的一篇笔记。
1 前言
原型: 每个函数天生自带的 prototype 对象数据类型
作用: 由构造函数向 原型上 添加方法, 提供给该构造函数的所有实例使用
为了解决构造函数将方法书写在构造函数体内时造成的资源浪费
原型链:概念: 用 proto 串联起来的对象链状结构
作用: 为了对象访问机制服务(当你访问一个对象成员的时候, 为你提供一些服务)
注意: 只是 proto 串联起来的对象链状结构, 千万不要往 prototype 上靠
万物皆对象
在 JS 内, 任何一个数据类型其实都是对象
函数也是一个对象, 数组也是一个对象, 正则也是一个对象, ... =>
是对象, 就可以存储 键值对
以函数为例,当你书写完毕一个函数的时候,此时 函数数据类型 出现了, 同时该函数名也是一个对象数据类型
重要概念
-
每一个函数天生自带一个属性叫做 prototype, 是一个对象数据类型
-
每一个对象天生自带一个属性叫做 proto, 指向所属构造函数的 prototype
-
任何一个对象, 如果没有准确的构造函数, 那么看做是 Object 的实例
即只要是一个单纯的对象数据类型, 都是内置构造函数 Object 的实例
2 灵魂7问
//创建构造函数
function Fn(){}
const fn = new Fn();
问题1: fn 身上的 proto 是谁 ?
因为 fn 是 Person 的实例,根据 概念1 得到 fn.proto 指向所属构造函数的 prototype
function Fn(){}
const fn = new Fn();
console.log(fn.__proto__ === Fn.prototype);//true
问题2: Fn 的 proto 是谁?
Fn是一个构造函数, 同时也是一个函数, 同时也是一个对象,只要是对象就会有 proto 属性。
JS 内有一个内置构造函数叫做 Function, 只要是函数, 就看做 Function 的实例,任何一个函数数据类型所属的构造函数都是 Function
Fn看做是 Function 的实例,Fn所属的构造函数就是 Function,即Fn.proto 指向 Function.prototype
function Fn(){}
const fn = new Fn();
console.log(Fn.__proto__ === Function.prototype);//true
问题3: Fn.prototype 的 proto 是谁?
Fn.prototype 是函数天生自带的一个对象数据类型,只要是对象就会有 proto 属性
JS 内有一个内置构造函数叫做 Object, 只要是单纯的对象, 都是 Object 的实例。
Fn.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型,就可以把 Fn.prototype 看做是 Object 的实例
Person.prototype 的 proto 就是 Object.prototype
function Fn(){}
const fn = new Fn();
console.log(Fn.prototype.__proto__ === Object.prototype);//true
问题4: Function 的 proto 是谁?
Function 是一个构造函数, 同时也是一个函数, 同时也是一个对象
只要是对象就会有 proto 属性
JS 内有一个内置构造函数叫做 Function, 只要是函数就是 Function 的实例
Function 自己本身是一个内置构造函数, 本身也是一个函数,而Function 也自己是自己的实例, 自己是自己的构造函数
在 JS 内管 Function 叫做顶级函数,所有Function.proto 就是 Function.prototype
function Fn(){}
const fn = new Fn();
console.log(Function.__proto__ === Function.prototype);//true
问题5: Function.prototype 的 proto 是谁?
Function.prototype 是函数天生自带的一个对象数据类型 ,只要是对象就会有 proto 属性
Function.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型,把 Function.prototype看做是 Object 的实例 Function.prototype 的 proto 就是 Object.prototype
function Fn(){}
const fn = new Fn();
console.log(Function.prototype.__proto__ === Object.prototype);//true
问题6: Object 的 proto 是谁?
Object 是一个构造函数, 同时也是一个函数, 同时也是一个对象
只要是对象就会有 proto 属性,Object 也是一个函数(内置构造函数), 只要是函数就是 Function 的实例
Object 这个内置函数所属的构造函数依旧是 Function,即Object.proto 就是 Function.prototype
function Fn(){}
const fn = new Fn();
console.log(Object.__proto__ === Function.prototype);//true
问题7: Object.prototype 的 proto 是谁?
Object.prototype 是函数天生自带的一个对象数据类型,只要是对象就会有 proto 属性
在 JS 内, Object 是顶级对象, Object.prototype 是顶级原型
Object.prototype 是唯一一个没有 proto 的对象数据类型,
即 Object.prototype 的 proto 是 null
function Fn(){}
const fn = new Fn();
console.log(Object.prototype.__proto__ === null);//true
3 对象访问机制
当访问对象成员的时候,会首先在自己本身上查找,如果有,直接使用,如果没有,会自动去自己的 proto 上查找。
如果还没有,再去__proto__上查找,一次类推,直顶级原型都没有,返回undefined。
function Fn(){}
const fn = new Fn();
Fn.prototype.a = ()=>{
console.log('Fn.prototype.a');
//自定义构造函数的.prototype中添加的内容,给该构造函数的所有实例使用。
}
Function.prototype.b = ()=>{
console.log('Function.prototype.b');
// Function.prototype中添加的内容,所有函数数据类型都可以使用。
}
Object.prototype.c = ()=>{
console.log('Object.prototype.c');
// Object.prototype中添加的内容,所有数据类型都可以使用。
}
//自定义构造函数的.prototype中添加的内容,给该构造函数的所有实例使用。
fn.a()//Fn.prototype.a
// Function.prototype中添加的内容,所有函数数据类型都可以使用。
// fn.b();
// 会报错 TypeError: fn.b is not a function
Fn.b();//Function.prototype.b
Function.b();//Function.prototype.b
Object.b()//Function.prototype.b
// Object.prototype中添加的内容,所有数据类型都可以使用。
fn.c();//Object.prototype.c
Fn.c();//Object.prototype.c
Function.c();//Object.prototype.c
Object.c()//Object.prototype.c
结论:
Object.prototype中添加的内容,所有数据类型都可以使用。
Function.prototype中添加的内容,所有函数数据类型都可以使用。
自定义构造函数的.prototype中添加的内容,给该构造函数的所有实例使用。
prototype只用于添加,不用于任何访问。