• 原型链理解(1)


    1.首先定义一个构造函数Set

    function Set() { //构造函数的开头要大写,区别于普通函数
    
    }

    2.这个构造函数,有一个原型对象 prototype。这个属性即使不手动定义,是每个function定义以后就会默认自带的属性

    Set.prototype = { 
        
    }

      1)什么是原型对象,就是Set 构造函数构造出来的对象的原始对象,new 出来的对象,都是基于这个原型对象生成的

      2)不可以直接这样等号右边写{  } 这样会把原型和构造的联系给覆盖掉

    3.Set.prototype 打印出来就是一个对象,这个对象就是原型对象。

    4.这个原型对象有一个constructor 属性,指向这个原型对象的构造方法(构造函数)。所以这个原型是不可以被重写的。只能

    Set.prototype.div = "sdds"; 这样给它赋值。

    5.  这个原型有一个指针指向它的构造函数,。函数是一个对象,Function类的实例对象,所以constructor在内存里面存放的是对函数的引用,是引用类型。

    6.定义一个对象setChile,由Set构造函数构造出来。(什么是构造函数,就是构造它的函数,谁创建了这个对象,谁就是这个对象的构造函数。)

    function Set() { 
        this.age = 32;
    }
    Set.prototype.name = 'set';
    var setChile = new Set();

    7.那么setChile 拥有一个属性__proto__,这个属性指向它的原型(这个对象原始的形态,就叫它的原型, 这个对象的初始形态)。

    先把这句话打印出来直观的解释一下

    这个对象有一个__proto__指向原型。其实属于原型里面的属性和方法,并没有在对象里面单独创建出来,而是通过这个__proto__去获取出来的。

    我把这个对象打印出来,可以看到setChild其实只有一个属性age。但是都知道如果打印setChild.name也是可以打印出来的。其实本质上是通过

    __proto__这个引用获取出来的,并不会去重新创建出来。但是构造Set()里面的age属性是会去内存里面创建出来的。

    左边就是这个对象的属性,我把我理解的画出来了。

    8.所谓的setChild.__proto__指向构造的原型,就是setChild.__proto__ == Set.prototype。指向就是 =,为什么用指向,因为它们等号右边是一个对象,对象是引用类型,所以它们是指针,指向内存里面的对象。其实把指向理解成 = 就可以了。

    9.__proto__ 和 prototype 其实是一个东西。没什么区别。所以如果是原型里面的属性,所有的对象的那个属性都指向的是内存里面同一个地方。

    10.修改构造出来实例对象的__proto__属性,就是去更改原型对象(Set.prototype)的属性。__proto__指向对象的原型。(原型对象,对象的原型听着就感觉很糊涂,听起来有什么区别,真的想骂人)(但是他们本来就是一个东西。只是一个单纯的说它是原始的那个对象,而对象的原型,针对的setChile这个对象来讲的,它的原型对象)

    11.setChile 这个对象的构造函数就是Set,构造它的函数。但是这个constructor并不是这个对象本身的属性,是从它的__proto__里面获取的。

    我可以证明为什么是从__proto__里面获取的(从原型的属性里面获取的)。

    证明1:

    如果更改了原型,把原型给重置了,原型里面的constructor就没有了,打印 

    setChile.constructor == Set 就是 false.如果不是从原型里面获取,那么怎么会原型没了,它的构造就是false了。

    证明2:

    直接打印Set,它本身属性里面是没有constructor的,它的construtor就是在__proto__里面获取的。

    12.setChile这个对象的属性,会先去{  age: 32 } 里面找,找不到这个属性,才会去查询它的原型,看看它有没有这个属性,再读出来。原型的所有属性它都有

    即使prototype.age在下面去重写age,没有用的。打印出来仍然是 32。但是这个对象的原型里面的age仍然是100(

    console.log(setChile.__proto__.age);)浏览器打印这个值,会是100。

    13.

    对象的__proto__,这个对象的原始,这个对象的原型

    对原型链的理解其实就这些了。

    通过原型链继承的时候,就是运用的_proto__这个东西,一个对象的拥有 它.__proto__上面的所有属性,包括__proto__的构造constructor。(已经在上面详细的阐述了这个过程)

    下面的不看也可以

    其他1. function函数 是 Function 的对象,所以所有函数的构造都是Function 

    console.log(Set.constructor == Function); //true

    其他2.如果要关系setChild 和 Object 对象的关系,那要看继承了。准备晚点再写

    其他3.为什么要用构造和原型混合的写法,这样去写js创建对象。

        因为,构造函数创建出来的对象里面的属性都是重新创建的,会去占内存。那么全都用原型去创建,不使用构造怎么样,也不行。已经知道了对象对原型属性的

        获取的时候,都是使用的引用,全是同一个内存。所以,你把值定义在原型上面的时候,如果是引用类型,就会出现数据被覆盖的问题。举个例子

        

        在实例对象上修改name值,怎么也不应该去修改创建它的初始值。但是js的机制就是通过原型链引用获取值。为了避免这样的情况,所以把所有的引用类型的变量都定义在构造里面,这样就避免了初始化数据(公用且不应该被修改的数据)会被重写这样的事情。

        

  • 相关阅读:
    Flutter | 如何优雅的解决依赖版本冲突
    Flutter包依赖冲突解决方法
    Cannot run with sound null safety because dependencies don't support null safety
    软件工程实践2019第三次作业
    【题解】洛谷 P3704 [SDOI2017]数字表格
    关于学历和素质成正比的隐晦思考
    斐波那契数列通项公式
    某不知名比赛游记
    CCPC-final 2020 北京游记
    EC-final 2020-2021 西安游记
  • 原文地址:https://www.cnblogs.com/chenyi4/p/11957867.html
Copyright © 2020-2023  润新知