概念 :
+ 原型: 构造函数天生自带的一个对象数据类型, 存储方法提供给实例使用的
+ 原型链: 使用 __proto__ 串联起来的对象链状结构, 为了对象访问机制使用的
目录
问题 2: p1(Person 的实例对象) 身上的 __proto__ 指向谁 ?
问题 3: Person 的 __proto__ 指向谁 ?
问题 4: Person.prototype 的 __proto__ 指向谁 ?
问题 5: Function 的 __proto__ 指向谁 ?
问题 6: Function.prototype 的 __proto__ 指向谁 ?
问题 7: Object 的 __proto__ 指向谁 ?
问题 8: Object.prototype 的 __proto__ 是谁 ?
原型 :
构造函数概念:
+ **每一个函数天生自带一个属性, 叫做 prototype , 是一个 对象数据类型**
+ 构造函数也是一个函数, 所以构造函数也会有 prototype
=> 作用: 由构造函数向 原型 prototype 上 添加方法, 提供给该构造函数的所有实例使用
=> 为了解决构造函数将方法书写在构造函数体内时造成的资源浪费
+ 在构造函数天生自带的 prototype 内有一个叫做 constructor 的属性
=> 表名我是谁自带的 prototype
=> 指向自己所属的构造函数
+ 是一个对象, 我就可以向里面添加一些成员
实例对象概念:
+ **每一个对象天生自带一个属性, 叫做 __proto__, 指向所属构造函数的 prototype**
+ 实例对象也是一个对象, 所以实例对象也会有 __proto__
原型相关概念 :
1. 每一个函数天生自带一个属性, 叫做 prototype , 是一个对象数据类型
2. 每一个对象天生自带一个属性, 叫做 __proto__ , 指向所属构造函数的 prototype
3. 任何一个数据类型, 如果不确定构造函数是谁, 那么就看做是 Object 的实例
=> 只要是一个单纯的对象数据类型, 那么都是内置构造函数 Object 的实例
原型链 :
=> 概念: 使用 __proto__ 串联起来的对象链状结构
+ 从任何一个数据结构出发, 最终都能找到 Object.prototype
+ 作用: 为了对象访问机制服务
(当你需要访问一个对象成员的时候, 为你提供一些服务)
=> 首先在自己身上查找, 自己身上有, 就直接使用, 停止查找
=> 自己没有, 就会自动去自己的 __proto__ 上查找
=> 如果还没有, 就再去 __proto__ 上查找
=> 直到 Object.prototype 上都没有, 返回 undefined
=> 注意: 只是 __proto__ 串联起来的对象链状结构, 千万不要往 prototype 上靠
万物皆对象 :
+ 在 JS 内, 任何一个数据类型其实都是对象
+ 函数也是一个对象, 数组也是一个对象, 正则也是一个对象, ...
=> 是对象, 就可以存储 键值对
+ 以函数为例
=> 当你书写完毕一个函数的时候
=> 此时 函数数据类型 出现了, 同时该函数名也是一个对象数据类型
// 万物皆对象
// 当函数创建完毕以后, 可以把 fn 当做一个对象名来使用
function fn() {
console.log('你好 世界')
}
// 我把 fn 当做对象名来使用
fn.a = 100
// 此时是把函数内 函数体 空间的代码执行掉
// 和函数对象空间内的数据没有任何关系
fn()
console.log(fn)
console.dir(fn)
// 数组同时也是一个对象空间
let arr = [100, 200, 300, 400]
// 完全可以把 arr 当做一个对象名来使用
arr.age = 18
// 当你遍历数组的时候, 只是遍历数组中的数组空间
arr.forEach(item => {
console.log(item)
})
console.log(arr)
prototype 和 __proto__ 有什么区别
1. 名字不一样
2. 有可能指向同一个对象空间
=> prototype 前面主语一定是函数
=> __proto__ 前面的主语一定是对象
我们的一个原型对象 , 它关系着两个数据 , 一个是构造函数 , 一个是构造函数的实例 ,
如果你用 构造函数 本身来访问他 , 那就叫 prototype ,
如果你用 实例 来访问他 , 那么就叫 __proto__
案例 :
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
Person.prototype.sayHi = function () { console.log('hello world') }
const p1 = new Person('Jack', 18, '男')
问题 :
问题 1: Person.prototype 指向谁 ?
=> 指向天生自带的 对象数据类型
问题 2: p1(Person 的实例对象) 身上的 __proto__ 指向谁 ?
=> 指向所属构造函数的 prototype
=> 因为: p1 所属的构造函数是 Person
=> 所以: p1.__proto__ 指向所属构造函数的 prototype ( Person.prototype )
// 问题 2 证明 :
console.log(p1.__proto__ === Person.prototype)
// true
问题 3: Person 的 __proto__ 指向谁 ?
=> Person 是一个构造函数, 同时也是一个函数, 函数本身也是一个对象
=> 只要是对象就会有 __proto__ 属性
=> 因为: 函数是 JS 的内置数据类型的一种, 所以 JS 内就有一个内置构造函数叫做 Function
=> 只要是一个函数, 那么就看做是属于 Function 这个内置构造函数的 实例
=> 任何一个函数数据类型所属的构造函数都是 Function
=> Person 看做是 Function 的实例
=> Person 所属的构造函数就是 Function
=> 那么 Person.__proto__ 指向 Function.prototype
// 问题 3 证明 :
console.log(Person.__proto__ === Function.prototype)
// true
问题 4: Person.prototype 的 __proto__ 指向谁 ?
=> Person.prototype 是函数天生自带的一个对象数据类型
=> 只要是对象就会有 __proto__ 属性
=> JS 内有一个内置构造函数叫做 Object, 只要是单纯的对象, 我们说他都是 Object 的实例
=> Person.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型
=> 把 Person.prototype 看做是 Object 的实例
=> Person.prototype 的 __proto__ 就是 Object.prototype
// 问题 4 证明 :
console.log(Person.prototype.__proto__ === Object.prototype)
// true
问题 5: Function 的 __proto__ 指向谁 ?
=> Function 是一个天生自带的内置构造函数, 但同时也是一个函数, 同时也是一个对象
=> 只要是对象就会有 __proto__ 属性
=> JS 内有一个内置构造函数叫做 Function, 只要是函数就是 Function 的实例
=> Function 自己本身是一个内置构造函数, 本身也是一个函数
=> Function 所属的构造函数是 Function
=> Function 自己是自己的实例, 自己是自己的所属构造函数
=> 在 JS 内管 Function 叫做 顶级函数
=> Function.__proto__ 就是 Function.prototype
// 问题 5 证明 :
console.log(Function.__proto__ === Function.prototype)
// true
问题 6: Function.prototype 的 __proto__ 指向谁 ?
=> Function 天生自带一个 prototype 是一个对象数据类型
=> 只要是对象就会有 __proto__ 属性
=> Function.prototype 是一个天生的对象数据类型, 并且是一个单纯的对象数据类型
=> 我们就把 Function.prototype 看做是 Object 的实例
=> Function.prototype 所属的构造函数就是 Object
=> Function.prototype 的 __proto__ 就是 Object.prototype
// 问题 6 证明 :
console.log(Function.prototype.__proto__ === Object.prototype)
// true
问题 7: Object 的 __proto__ 指向谁 ?
=> Object 是一个天生自带的内置构造函数, 但同时也是一个函数, 同时也是一个对象
=> 只要是对象就会有 __proto__ 属性
=> Object 也是一个函数, 只要是函数就是内置构造函数 Function 的实例
=> Object 这个内置函数所属的构造函数依旧是 Function
=> Object.__proto__ 就是 Function.prototype
// 问题 7 证明 :
console.log(Object.__proto__ === Function.prototype)
// true
问题 8: Object.prototype 的 __proto__ 是谁 ?
=> Object 天生自带一个 prototype, 是一个对象数据类型
=> Object.prototype 是函数天生自带的一个对象数据类型
=> 只要是对象就会有 __proto__ 属性
=> 在 JS 内, Object 是顶级对象 , Object.prototype 是顶级原型
=> Object.prototype 是唯一一个没有 __proto__ 的对象数据类型
=> Object.prototype 的 __proto__ 是 null
// 问题 8 证明 :
console.log(Object.prototype.__proto__)
// null
最终版图解 :
梳理不易 , 大佬们看着觉得还不错的希望能给点个赞支持一下咯 , 谢谢 ^_^ ~