• 一文搞懂原型和原型链


    在了解原型和原型链之前首先得明确它俩是什么东西:

    原型:prototype
    又称显示原型
    1、原型是一个普通对象
    2、只有构造函数才具备该属性
    3、公有属性可操作

    隐式原型:__proto__
    1、只有对象(普通对象、函数对象)具备
    2、私有的对象属性,不可操作

    有了上面的概念之后,我们再来探讨一下什么是原型和原型链。

    原型(显示原型) : prototype

    我们定义一个字符串变量的时候,该字符串本身是不具备任何方法的,但是可以调用字符串方法。

    let str = 'hello'  // new String()
    console.log(str);
    console.log(str.length);
    

    在这里插入图片描述

    其实我们在定义一个字符串变量的时候,隐式的实例化了new String()这个构造函数,所以我们才可以使用字符串方法。

     console.log(new String());
    

    在这里插入图片描述

    这个length就是String的原型方法ptototype,字符串本身有没有这个方法不重要,字符串的原型上有个方法就可以了。
    原型的本质是一个普通对象,所以我们可以利用对象.属性的方式调用方法。
    如果我们用字符串调用一个DCodes(),该方法在字符串属性上没有并不存在,调用该方法会报错。
    在这里插入图片描述
    我们给String的原型添加一个DCodes方法,字符串就可以调用该方法了。

    String.prototype.DCodes = function(){
           console.log('你好DCodes');
    }
    str.DCodes() // 你好DCodes
    

    利用原型可以干什么呢?上面也说了,构造函数才具备原型,我们创建一个构造函数,可以通过实例化这个构造函数来调用原型方法和原型属性。

    // 构造函数
    function Person(){
             this.name = '东方不败'
    }
    let per = new Person()
    console.log(per);
    

    在这里插入图片描述
    原型的本质是一个对象,那么给Person这个原型添加一个方法

    function Person(){
             this.name = '东方不败'
    }
    Person.prototype.sum = function(a,b){return a + b}
    let per = new Person()
    console.log(per);
    console.log(per.sum(1,2));
    

    在这里插入图片描述
    构造函数记录了当前原型对象产生的归属,原型是基于那个构造函数构建的,那么constructor指向的就是那个构造函数,这里的constructor指向的就是Person()函数。


    __proto__隐式原型

    隐式原型只有对象(普通对象、函数对象)才具备,并且隐式原型是一个私有的对象属性,不可操作。
    上面也提到过,我们定义了一个字符串,实际上是隐式的new String()String()的原型上有length,所以字符串可以调用length方法,显示原型prototype是构造函数才具备的,普通对象是没有的,那么普通对象是怎么调用构造函数的原型方法的呢?答案就是普通对象具有隐式原型,隐式原型全等于显示原型

    let hello = 'hello'
    console.log(hello.__proto__ === String.prototype);  // true
    

    在这里插入图片描述
    也就是说,普通对象的隐式原型__proto__等于构造函数的显示原型prototype,普通对象就可以调用构造函数的原型方法。
    谷歌浏览器中,隐式原型__proto__的写法为: [[Prototype]]
    在这里插入图片描述
    到这里就构成了原型链,用字符串调用字符串方法的时候,字符串会在__proto__寻找对应的字符串方法,__proto__等于prototype,也就是String()构造函数,如果String()的构造函数没有该方法,那么String()会继续向上寻找,原型prototype是一个对象,那么对象就会有隐式原型__proto__String()的隐式原型__proto__Object(),然后会在Object()的原型prototype上寻找,如果Object()的原型prototype上不存在该属性,那么就会通过隐式原型__proto__继续向上寻找,直到找到对应的方法为止,如果没有找到,那么就会报错,该方法不存在。(这一段需要好好理解)
    这样向上寻找,最终总会有尽头,万物的原型终点是谁呢?
    字符串、数组、构造函数的原型最终都会指向Object,而Object的原型指向的是null
    在这里插入图片描述

    console.log(Object.prototype);
    

    在这里插入图片描述

    最后我们来看一下prototype、__proto__之间的关系:

    __proto__ === prototype 
    prototype == {}
    {}.__proto__ == Object.prototype
    ......
    
  • 相关阅读:
    【Linux】Linux环境基础开发工具使用—— vim | gcc & g++ | make & makefile | 进度条 | git
    【Docker学习】docker login/logout
    期货量化交易客户端开源教学第九节——新用户注册
    ndk 编译报错 find_library called with incorrect number of arguments
    ALEVEL数学、物理、化学、生物与国内考试的区别
    cmd 命令关闭占用端口
    Python Web开发 之 学生管理系统(2)[实现筛选,搜索,分页]
    mmdetection常见报错以及解决方案汇总
    JS基础习题
    js--promise、async 和 await 相关知识总结
  • 原文地址:https://www.cnblogs.com/wang-fan-w/p/17277765.html