JavaScript - js进阶 - 原型 prototype

原型 prototype

原型上存放函数

原型解释

  • 原型的单词是 prototype, 原型的这个名字是行业内共同认可的名字。
  • 原型本质是一个对象,理解为 JavaScript 自动帮我们添加的
  • 原型是 JavaScript 自动帮我们在定义构造函数的时候添加的
  • 所有构造函数的实例,共享一个原型
  • 原型上一般是挂载函数

原型 proto

  1. 实例的 proto 属性 等于 构造函数的 prototype

    p1.__proto__ === Person.prototype // true
    
  2. 不过由于不同浏览器的兼容性问题,我们使用的时候,都只会使用 构造函数的prototype

  3. 实例的 proto 只是为了方便我们开发的时候查看数据,是不会手动修改和操作它的。

原型对象 - 三角关系图

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>原型对象 - 三角关系</title>
    </head>
    <body></body>
    <script>
        // 自定义构造函数: 给对象做分类, 便于管理
        // 对象: 数据(属性) 和 数据操作(方法)

        function Student(name, age) {
            this.name = name;
            this.age = age;
        }

        // JS世界中: 构造函数, js是男的
        // JS不允许单身出现: 一定会分配一个女的

        // 将这种 函数(一般指构造函数) 一定有一个对象: 原型对象
        // 找到函数的原型对象: 函数名.prototype
        console.log(Student.prototype);

        // 默认的原型对象中: 只有一个属性 constructor,指向构造函数(一夫一妻制)
        console.log(Student.prototype.constructor); // f Student

        // 再次证明: 老公的老婆的老公是 老公
        console.log(Student.prototype.constructor === Student); // true

        // 原型对象的价值: 用于管理 方法
        // Student.prototype.属性名 = '属性值'                       // 一般不会添加普通数据
        // console.log(Student.prototype)

        // 实际只给原型对象添加方法( 挂载原型方法 : 将函数放到原型对象里面)
        Student.prototype.study = function () {
            console.log(this.name + "正在学习");
        };

        // 产生孩子: new
        const s1 = new Student("张三", 29);
        console.log(s1);

        // 对象内部:只有属性(构造函数给的), 但是可以找到构造函数对应的原型对象: 里面的内容, 对象都可以无条件访问
        console.log(s1.study);
        s1.study(); // study内部的this指向s1

        // 孩子找妈妈: 孩子对象.__proto__(谷歌支持: 不是所有浏览器都支持: 有兼容性)
        console.log(s1.__proto__ === Student.prototype); // true

        // 总结
        // 自从有了原型对象
        // 1. 构造函数的属性:如果是方法, 放到原型对象中: 原型对象只有一个: 方法内存只占一份
        // 2. 原型对象是一个对象: 属性方法是内部的内容, 不受全局污染: 安全
    </script>
</html>

原型的关系

所有的构造函数都是Function的实例

Array 和 Person 和 Date 等都是 Function的实例

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body></body>
    <script>
        // 原型关系: 三角关系(爸爸 妈妈 孩子)

        // 所有函数都有Function创建: new Function()
        function Student(name, age) {
            this.name = name;
            this.age = age;
        }

        // 问题1: Student由 Function创建的

        // 分析
        // Student是Function的孩子
        // Function是构造函数
        // 函数一定有原型对象

        // 证明

        // Function有原型对象
        console.log(Function.prototype); // f 函数: 函数跟对象一样, 都是复合数据类型

        // Function的原型对象能找到Function?
        console.log(Function.prototype.constructor === Function); // true

        // 自定义构造函数Student此时是孩子(对象) : 有妈妈
        console.log(Student.__proto__ === Function.prototype); // true

        // 构造函数: 也是孩子, 也存在原型三角关系
    </script>
</html>

原型链

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body></body>
    <script>
        // 已有结论

        // 1. 对象: 可以无条件访问原型对象里面的内容
        // 2. 原型对象: 由Object产生, 指向Object.prototype: 顶级原型对象

        // 一个自定义构造函数的实例(new得到的对象) 可以访问构造函数自己的原型方法
        // 自己的原型对象: 指向Object的原型对象

        // 这种链条关系: 称之为原型链
        // 原型链的作用: 就是JS如何实现面向对象中最重要的一个特性: 继承
        // 只要是原型链上的内容: 对象就可以无条件访问
        function Student(name, age) {
            this.name = name;
            this.age = age;
        }

        // 给Studnent挂载原型方法
        Student.prototype.study = function () {
            console.log(this.name + "正在学习");
        };

        const s = new Student("安琪拉", 18);

        // console.log(s)

        // 1. 访问自己: 自己有不求人
        console.log(s.name, s.age);

        // 2. 访问原型对象: 自己妈妈
        s.study();
        console.log(s.constructor); // 等价于: s.__proto__.constructor

        // 3. 访问顶级原型对象: 自己外婆
        console.log(s.toString());

        // 继承的优点: 代码可以复用(别人有的, 直接使用即可)
        // 需求: 项目中有一个say的功能: 所有数据都可以调用

        // console.log(new Number(1))
        // Object.prototype是顶级原型对象: 所有对象最终都继承Object.prototype
        Object.prototype.say = function () {
            console.log(this);
        };

        let num = 1;
        let str = "abc";
        let bl = true;
        let s2 = new Student("仲未", 200);

        num.say();
        str.say();
        bl.say();
        s2.say();
    </script>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Henry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值