LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

原型和原型链

2023/2/15

原型的五条规则

  1. 所有的引用数据类型都具有对象的特性,可以自由的扩展属性
  2. 所有的对象都有 proto 属性, 它的值是一个对象 proto 也叫隐式原型
  3. 所有的函数都有 prototype 属性, 它的值也是一个对象 prototype 也叫显式原型
  4. 引用类型中 proto 指向他构造函数的 prototype 也就是对象的隐式原型指向它构造函数的显式原型
  5. 当我们获取对象身上不存在的属性时,那么他就会去 proto 中获取

引用数据类型 : Object 、Array 、Function 、Date 、RegExp

使用原型有哪些优点/好处?

我们有一个构造函数,使用这个构造函数实例的对象都有一个 jump() 方法

function Person (name,age){
    this.name = name
    this.age = age
      jump(){
     console.log('jump')   
      }
 }
const per1 = new Person('小明',12)
const per2 = new Person('小红',13)
per1.jump()
per2.jump()

上面代码中 jump方法 在堆中存储效果是这样的

入上图所示会在堆内存中开辟两块空间存放同一个函数
那么我们怎么解决这个问题呢? 原型?

function Person (name,age){
    this.name = name
    this.age = age
 }
const jump = function (){
     console.log('jump')   
}
// 将jump 方法绑定在 People构造函数的显式原型上
Person.prototype.jump = jump

const per1 = new Person('小明',12)
const per2 = new Person('小红',13)
per1.jump()
per2.jump()

我们将公共的方法绑定在构造函数的prototype上 根据上面的第四条规则

引用类型中 proto 指向他构造函数的 prototype 也就是对象的隐式原型指向它构造函数的显式原型

当我们访问实例对象身上不存在的方法时则会通过 proto 访问到构造函数的 prototype 上

什么又是原型链呢?

看下面这段代码:

function Person(name) {
  this.name = name
}

var nick = new Person("nick")
nick.toString
// ƒ toString() { [native code] }

按照道理来说 nick 是 Person构造函数的实例 并且 Person的构造函数上也没有 toString方法 , 那么为什么 nick 可以获取到 toString 方法呢?

这就是原型链 nick 先从自身出发 发现自身并没有 toString 方法 然后 向上找, 找到了构造函数 prototype ,发现也没有该方法 , 然后构造函数 的 prototype 本质也是一个对象 就会接着通过 proto 向上找 找到了 Object.prototype , 所以就找到了 Object.prototype 下的 toString 方法。

最上级的null 是为了避免死循环 Object.prototype 的隐式原型指向 null。

instanceof 是什么? 是否可以手写实现 instanceof?

instanceof 是检查构造函数的显式原型是否出现在 目标对象的原型链中任意位置

// 检测 R的原型是否出现在L的原型链中
function instance_of(L,R){
    //先验证 R 的数据类型
  const typeArr = ['number','string','null','undefined','boolean','symbol']
  if(typeArr.includes(typeof R)) return
  // 获取 R 的显式原型 
    const RPT = R.prototype
  // 获取 L 的隐式原型
  const LP = L.__proto__
  while(true){
    if(RPT === LP){ // 相等返回
        return true
    }
    // 找到了最底层
    if(LP === null){
      return false
    }
    // 没有找到则向上一层继续
    LP = LP.__proto__
  }
}

实现思路 :
如果 构造函数的显式原型 在 对象的原型链中 那么 两者是相等的
如果两者不相等 则向上寻找继续比较 直到null

showimg