认识原型及原型链

77 阅读4分钟

原型

  • 每一个函数都有一个属于自己的原型
    • 作用: 我们会在原型内部放一些公共的方法, 目的不是为了让构造函数去使用, 而是为了让实例化对象去使用

        const arr = new Array()
        const obj = new Object()
      

      找到数组构造函数的原型

        const arr = new Array()
        console.log(arr.__proto__)
        console.log(Array.prototype)
      

      找到对象构造函数的原型

        console.log(Object.prototype)
      
    • 任何一个数组的构造函数 都是 Array

    • 任何一个对象的构造函数 都是 Object

    • 任何一个函数的构造函数 都是 Function

万物皆对象

  • 对象:
    • 含义1: 一种数据格式 {key: value, key2: value2}

    • 含义2: 某一类事务的实例 (某一类内容中的 真实个体)

        const arr = [1, 2, 3]
        const arr1 = [1, 2, 3, 4]
        这个 arr1 就是Array这一类内容中的某一个 真实个体, 数组也可以算作一个对象(Array 这一类事务中的一个个体)
      
        const fn = () => {console.log(1)}
        函数也是一个对象(属于 Function 这一类事务中的一个个体)
      

原型链

  • 查找对象的某一个属性:
    • 先在对象内部开始查找, 找到直接使用, 然后停止查找

    • 如果没有找到, 会找对象的 obj.proto, 如果找到直接使用, 然后停止查找

    • 如果这里没找到, 会继续去对象的 proto 查找, 找到直接使用, 然后停止查找

    • 如果还是没找到, 会继续向上查找 ...

    • 直到找到顶层作用对象 Object.prototype, 找到就是用, 找不到 undefined

        function Person (name) {
                this.name = name
            }
            Person.prototype.sayHi = function () {
                console.log(100)
            }
            const p = new Person('abc')
      
  • 问题1: p 的 proto 指向谁?
    • p 是 Person 的实例化对象

    • proto 指向自身构造函数的原型

    • p.__proto === Person.prototype

  • 问题2: Person 的 proto 指向谁?

    • Person 是构造函数, 本质上函数
    • 只要是一个函数, 他就是 Function 的实例
    • Person.proto 指向了 他的构造函数的原型, 构造函数是 Function, 那么构造函数的 原型 Function.prototype
    • Person.proto === Function.prototype
  • 问题3: Person.prototype 的 proto 指向谁?

    • Person.prototype 其实就是 构造函数 Person 的原型对象, 本质上就是对象
    • 只要是一个 对象, 他就是 Object 的实例
    • Person.prototype.proto 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
  • 问题4: Function 的 proto 指向谁?
    • Function 是构造函数, 本质上就是一个函数
    • 只要是一个函数, 他就是 Function 的实例
    • Function.proto 指向了 他的构造函数的原型, 构造函数 Function, 那么 构造函数的原型 Function.prototype
    • Function.proto === Function.prototype
  • 问题5: Function.prototype 的 proto 指向了谁?
    • Function.prototype 其实就是 构造函数 Function 的原型对象, 本质上是对象
    • 只要是一个对象, 他就是 Object 的实例
    • Function.prototype.proto 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
    • Function.prototype.proto === Object.prototype
  • 问题6: Object 的 proto 指向了谁?
    • Object 是一个构造函数, 本质上还是一个函数
    • 只要是一个函数, 那么他的构造函数 就是 Function
    • Object.proto 指向了他的构造函数的原型, 他的构造函数是 Function, 那么构造函数的原型 Function.prototype
    • Object.proto === Function.prototype
  • 问题7: Object.prototype 的 proto 指向了谁?
    • Object.prototype 是构造函数 Object 的原型对象, 本质上就是一个对象

    • 但是重点: Object.prototype 是 JS 顶层的对象

    • Object.prototype.proto === null

        console.log('1.', p.__proto__ === Person.prototype)       // true
      
        console.log('2.', Person.__proto__ === Function.prototype)       // true
      
        console.log('3.', Person.prototype.__proto__ === Object.prototype)       // true
      
        console.log('4.', Function.__proto__ === Function.prototype)       // true
      
        console.log('5.', Function.prototype.__proto__ === Object.prototype)       // true
      
        console.log('6.', Object.__proto__ === Function.prototype)       // true
      
        console.log('7.', Object.prototype.__proto__)       // null
      

判断数据类型

    1. typeof 判断基本数据类型

         console.log(typeof('123'))
         console.log(typeof(123))
         console.log(typeof(true))
      
    1. constructor 可以判断当前数据的构造函数是谁
    • 问题1: 能够判断引用数据类型

      • 但是! 这个属性其实就是对象内的一个属性
      • 我们可以拿到这个对象, 然后修改他的属性值
    • 问题2: 不能判断 undefined 和 null

        const arr = [1, 2, 3]
      
        Array.prototype.constructor = { a: 1 }
        console.log(Array.prototype.constructor)        // {a: 1}
        console.log(arr.__proto__.constructor === Array)          // false
      
        console.log(undefined.constructor)  // undefined 内部没有 constructor 所以我么不能这样去判断
      
    1. instanceof 可以判断左边的构造函数是否等于右边的构造函数

    • 语法: 检测的数据 instanceof 构造函数

    • 问题: 不能判断 undefined 和 null

        const arr = [1, 2, 3]
      
        console.log(arr instanceof Array)   // true
      
        console.log(arr instanceof Function) // false
      
        console.log(undefined instanceof Array) // false
      
  • 4.Object.prototype.toString.call(要判断的数据结构)

    • Object 这个构造函数的原型内部有一个toString的方法

    • 这个方法能够帮我们将数据结构转为字符串的形式 '[object 数据结构]'

    • 我们在使用的时候 如果需要判断其他数据类型, 需要使用 .call这个方法改变内部 this 指向

    • 这个方法任何数据类型都能准确判断

        const obj = {
            a: 1,
            b: 2
        }
      
        console.log(Object.prototype.toString.call(obj))    // [object Object]
      
        console.log(Object.prototype.toString.call(undefined))  // [object Undefined]