• JS原型和原型链的理解


    构造函数创建对象

    我们首先使用构造函数来创建一个对象。

    function A () {
    
    };
    
    let a = new A();
    a.value = 'a';
    console.log(a.value); //输出的结果为a.

    prototype

    每一个函数都会有一个prototype属性(只有函数才具有的属性),prototype属性指向的是调用构造函数创建的实例的原型。原型指的是每一个javascript对象在创建的时候(null除外)都会与之关联的另一个对象。而每一个对象都会从原型中继承该属性。

    function A () {
    
    };
    
    A.prototype.value = 'A';
    let a1 = new A();
    let a2 = new A();
    a1.value = 'a1';
    
    console.log(a1);    //输出a1 --来自实例。
    console.log(a2);    //输出A --来自原型。
    
    delete a1.value;
    console.log(a1);    //输出A --来自原型。

    在以上例子中,需要访问a1中的value时,会在这该对象中搜索名为value的属性,因为value在该对象中的确存在,因此直接返回该值而不必再去搜索原型;同样的因为在a2中不存在value,因此会向上搜索原型,结果在原型中查找出了value属性。

    当在对象中添加一个属性时,这个属性就会屏蔽在原型对象中保存的同名属性(a1中的value屏蔽了A中的value)。也就是说添加了这个属性阻止我们访问原型中的那个属性,但不会修改那个属性。不过使用delete操作符则可以完全删除实例的属性,从而重新访问到原型中的属性。

    用一张图来表示构造函数和原型的关系:

    _proto_

    这是每一个对象都具有的属性(null除外),叫做_proto_,会指向该对象的原型。

    function A () {
    
    };
    
    let a = new A();
    
    console.log(a.__proto__ === A.prototype);  //true

    由此我们能够更新一下关系图得到:

     constructor

    既然构造函数和实例对象都能够指向原型,那么原型是否也包含一个属性来指向构造函数和实例对象的呢? 指向实例对象是没有的,因为一个构造函数可以生成多个实例对象。但是指向构造函数的却是有一个,这就要谈到今天要说的第三个属性constructor了。每一个原型都含有一个constructor属性用来指向关联的构造函数。

    function A() {
    
    };
    
    console.log(A.prototype.constructor === A);    //true

    所以再次更新关系图:

    综上我们可以得出一个结论就是:

    function A () {
    
    };
    
    let a = new A();
    
    console.log(a.__proto__ === A.prototype);    //true
    console.log(A.prototype.constructor === A);     //true

    原型的由来

    原型对象是通过Object构造函数生成的,结合之前所讲的_proto_指向构造函数的prototype。

    function A () {
    
    };
    
    console.log(A.prototype.__proto__ === Object.prototype);    //true 

     由此我们可以得出关系图为:

     

     接下来我们再看看Object.prototpye的原型来自什么。

    console.log(Object.prototype.__proto__);    //null

     引用阮一峰老师的《undefined和null的区别》

    null 表示“没有对象”,即该处不应该有值。

    所以 Object.prototype.__proto__ 的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。

    所以查找属性的时候查到 Object.prototype 就可以停止查找了。

    最后一张关系图也可以更新为:

    总结:

    A.__proto__ === Function.prototype 
    Function.prototype.__proto__ === Object.prototype
    Object.prototype.__proto__ === null 
    A.protype__proto__ == Object.prototype
  • 相关阅读:
    Spring05_基于注解的IOC和DI
    Spring02_基于XML的IOC
    Spring01_概述及程序的耦合
    设计模式六、单例模式
    设计模式五,建造者模式
    前后端分离异常统一处理
    vue qs.stringify 和JSON.stringify 区别
    设计模式四、抽象工厂模式
    设计模式三、工厂方法模式
    设计模式二、简单工厂模式——静态工厂模式
  • 原文地址:https://www.cnblogs.com/pipim/p/13099418.html
Copyright © 2020-2023  润新知