zoukankan      html  css  js  c++  java
  • 原型与原型链一知半解

    前言

    看过不少深入了解原型原型链系列,大体是明白不少,还是不够透彻!以下仅为个人总结和理解。

    初见各名词

    首先得了解这几个词:
    函数,构造函数,函数原型(实例原型),实例,实例对象,对象原型,原型,prototype,proto,constructor

    先看下面这个例子:

    function Person() {
    
    }
    function Foo() {
    
    }
    const foo = new Foo();
    const person = new Person();
    
    

    函数,构造函数:在上面的例子中构造函数就是Person

    函数原型(实例原型):后面会结合式子阐述。(我的理解是最初始的函数,他的属性所有函数使用)

    实例与实例对象:在上面的例子中,有构造函数Person、Foo,我们用new操作符实例化了foo实例对象、person实例对象

    原型对象与原型:后面会结合式子阐述。

    原型

    任何一个构造函数都会有prototype属性。打印构造函数Foo.prototype,Person.prototype你会发现

    console.log(Foo.prototype,Person.prototype);
    //{ constructor: f Foo(), __proto__: Object } { constructor: f Person(), __proto__: Object }
    

    Foo.prototype,Person.prototype它们都指向各自函数的原型对象

    a) 任何一个构造函数函数(Person,Foo),都拥有一个prototype属性,它指向这个函数的原型对象

    从打印出来的式子

    { 
      constructor: f Foo(),
      __proto__: Object 
    } 
    { 
    constructor: 
      constructor: f Person(),
      __proto__: Object 
    }
    

    不难看出 Person.prototype和Foo.prototype都有constructor和__proto__属性。

    而且Person.prototype.constructor和Foo.prototype.constructor都指向的是各自的构造函数本身。

    可以通过式子大胆验证下:

    console.log(Person.prototype.constructor === Person) // true
    console.log(Foo.prototype.constructor === Foo) // true
    

    b) 构造函数的prototype的constructor都是指向的构造函数的本身

    那么Person.prototype.__proto__和Foo.prototype.__proto__指向什么呢?

    console.log(Person.prototype.__proto__ === Object.prototype) // true
    console.log(Foo.prototype.__proto__ === Object.prototype) // true
    

    上式中的Person.prototype.__proto__和Foo.prototype.__proto__都指向Object.prototype

    c) Person.prototype的原型指向Object.prototype

    也就是说每个函数的原型都是Object的实例,那么Object.prototype的原型,new出来的foo,person的原型呢?

    console.log(foo.__proto__);//{ constructor: f Foo(), __proto__: Object } 
    console.log(person.__proto__);//{ constructor: f Person(), __proto__: Object }
    console.log(Object.prototype.__proto__);//null
    

    不难看出

    console.log(foo.__proto__===Foo.prototype);//true
    console.log(person.__proto__===Person.prototype);//true
    console.log(Object.prototype.__proto__===null);//true
    

    d) foo,person的__proto(实例的原型) === Person.prototype;因此把Person.prototype叫做实例原型。

    e) Person.prototype.proto(实例原型的原型) === Object.prototype;因此实例原型的原型指向的是Object.prototype。

    f) Object.prototype.proto(Object.prototype的原型) === null;因此Object.prototype.proto 的值为null,也就是Object.prototype没有原型。

    再上面的 b 项中式子拿下来(b.构造函数的prototype的constructor都是指向的构造函数的本身)

    console.log(Person.prototype.constructor === Person) // true
    console.log(Foo.prototype.constructor === Foo) // true
    

    那么Object.prototype.constructor是不是也是Object本身呢?

    console.log(Object.prototype.constructor===Object)//true
    

    g) Object.prototype.constructor === Object

    由此讶羽大佬的关系图也就清晰了
    原型链

    原型链

    由上面的分析,可以看出原型链实际上就是运行const foo = new Foo()语句(创建实例函数时),产生了一个链条反应,这个最顶端也就是原型链最顶端是Object.prototype.__proto__为null。

    总结:从一个实例对象往上查找构造这个实例的相关联对象(原型对象),这个关联的对象(原型对象)通过__prototo__属性再往上找创造他的原型对象,以此类推,一直往上找,直到Object.prototype的原型对象为null结束的过程。

    原型链是通过prototype的原型和__proto__的属性来完成原型链的查找。

    原型与原型链一知半解

  • 相关阅读:
    android_自定义布局
    二叉树_学习笔记
    栈的应用-四则表达式(C#代码实现)
    Android Fragment 生命周期
    Android Fragment之间传值
    Android ArrayAdpater 填充集合
    任务和返回栈
    XML Drawable与9-Patches
    《python语言程序设计》_第一章编程题
    CSS-文本超出部分省略号
  • 原文地址:https://www.cnblogs.com/yihan123/p/14213420.html
Copyright © 2011-2022 走看看