原型和原型链 ( prototype / __proto__ ) 详情版

本文深入探讨了JavaScript中的原型和原型链概念,包括构造函数的prototype属性、实例对象的__proto__属性,以及它们之间的关系。通过一系列的问题解答,阐述了对象链状结构的查找机制,并解释了万物皆对象的原理。此外,还讨论了prototype和__proto__的区别,以及它们在不同对象间的指向。最后,通过实例展示了原型链的工作方式,帮助理解JavaScript中对象的访问机制。
摘要由CSDN通过智能技术生成

 概念 :
        + 原型: 构造函数天生自带的一个对象数据类型, 存储方法提供给实例使用的
        + 原型链: 使用 __proto__ 串联起来的对象链状结构, 为了对象访问机制使用的


目录

原型 : 

原型相关概念 : 

原型链 : 

万物皆对象 : 

prototype 和 __proto__ 有什么区别

案例 : 

问题 : 

问题 1: Person.prototype 指向谁 ?

问题 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


最终版图解 : 

梳理不易 , 大佬们看着觉得还不错的希望能给点个赞支持一下咯 , 谢谢 ^_^ ~ 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值