什么是原型、原型链?原型和原型链的作用

news2024/11/15 8:32:57

1、ES6之前,继承都用构造函数来实现;

对象的继承,先申明一个对象,里面添加实例成员

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <script>
            // 1、实例成员 就是构造函数内部通过this添加的成员,uname age sing 都是实例成员,只能通过实例化的对象来访问
            function Weber(uname, age) {
                this.uname = uname;
                this.age = age;
                this.write = function() {
                    console.log("----------write--" + this.uname);
                }
            }

            var qyz = new Weber("青阳子", 36);
            qyz.write();
        </script>

    </body>
</html>

构造函数的调用需要用new操作符,而普通函数的调用又分很多种,但是都不会用到new操作符。所以,构造函数和普通函数的区别就在这个new操作符里,现在让我们来好好研究一下这个new操作符。

用new操作符创建对象时发生的事情:

第一步: 创建一个Object对象实例。

第二步: 将构造函数的执行对象赋给新生成的这个实例。

第三步: 执行构造函数中的代码

第四步: 返回新生成的对象实例

注意:原本的构造函数是window对象的方法,如果不用new操作符而直接调用,那么构造函数的执行对象就 是window,即this指向了window。现在用new操作符后,this就指向了新生成的对象。理解这一步至关重要

实例成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。

// 1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员

// 实例成员只能通过实例化的对象来访问

2、静态成员,就是在构造函数本身上添加的成员

Weber.sex = "男";
console.log(Weber.sex)  //男
console.log(qyz.sex) //undefined

3、构造函数存在的问题:浪费内存

var qyz = new Weber("青阳子", 36);
var lee = new Weber("李博涵", 4);
 
console.log(qyz.write === lee.write); //false 比较的是内存地址,不一致
//所有对象应该公用一套函数,以节省空间

1.构造函数原型 prototype

构造函数通过原型分配的函数是所有对象所共享的。

JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。

我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
 
<body>
    <script>
        // 1. 构造函数的问题. 
        function Weber(uname, age) {
            this.uname = uname;
            this.age = age;
            // this.write = function() {
            //     console.log('我会写博客');
 
            // }
        }
        Weber.prototype.write = function() {
            console.log('我会写博客');
        }
        var qyz = new Weber('青阳子', 38);
        var lee = new Weber('李博涵', 4);
        console.log(qyz.write === lee.write);
        // console.dir(Weber);
        qyz.write();
        lee.write();
        // 2. 一般情况下,我们的公共属性定义到构造函数里面, 公共的方法我们放到原型对象身上
    </script>
</body>
 
</html>

一个对象,我们也称prototype 为原型对象, 原型的作用是:共享方法

2.对象原型 __proto__

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

对象原型__proto__

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
 
<body>
    <script>
        function Weber(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Weber.prototype.write = function() {
            console.log('我会唱歌');
        }
        var qyz = new Weber('青阳子', 36);
        var lee = new Weber('李博涵', 4);
        qyz.write();
        console.log(qyz); // 对象身上系统自己添加一个 __proto__ 指向我们构造函数的原型对象 prototype
        console.log(qyz.__proto__ === Weber.prototype);
        // 方法的查找规则: 首先先看qyz 对象身上是否有 write 方法,如果有就执行这个对象上的write
        // 如果么有write 这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype身上去查找write这个方法
    </script>
</body>
 
</html>

__proto__对象原型和原型对象 prototype 是等价的

__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性, 因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

3. constructor 构造函数

对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。

此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
 
<body>
    <script>
        function Weber(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Weber.prototype.write = function() {
            console.log('我会写博客');
        }
        var qyz = new Weber('青阳子', 36);
        // 1. 只要是对象就有__proto__ 原型, 指向原型对象
        console.log(Weber.prototype);
        console.log(Weber.prototype.__proto__ === Object.prototype);
        // 2.我们Weber原型对象里面的__proto__原型指向的是 Object.prototype
        console.log(Object.prototype.__proto__);
        // 3. 我们Object.prototype原型对象里面的__proto__原型  指向为 null
    </script>
</body>
 
</html>

4.JavaScript 的成员查找机制(规则)

① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。

③ 如果还没有就查找原型对象的原型(Object的原型对象)。

④ 依此类推一直找到 Object 为止(null)。

⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
 
<body>
    <script>
        function Weber(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Weber.prototype.write = function() {
            console.log('我会写博客');
 
        }
        Weber.prototype.sex = '女';
        // Object.prototype.sex = '男';
        var qyz = new Weber('青阳子', 36);
        qyz.sex = '男';
        console.log(qyz.sex);
        console.log(Object.prototype);
        console.log(qyz);
        console.log(Weber.prototype);
        console.log(qyz.toString());
    </script>
</body>
 
</html>

5. 原型对象this指向

构造函数中的this 指向我们实例对象.

原型对象里面放的是方法, 这个方法里面的this 指向的是 这个方法的调用者, 也就是这个实例对象.

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
 
<body>
    <script>
        function Weber(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        var that;
        Weber.prototype.write = function() {
            console.log('我会写博客');
            that = this;
        }
        var qyz = new Weber('青阳子', 36);
        // 1. 在构造函数中,里面this指向的是对象实例 qyz
        qyz.write();
        console.log(that === qyz);
 
        // 2.原型对象函数里面的this 指向的是 实例对象 qyz
    </script>
</body>
 
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/372502.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu(虚拟机)的Anaconda 及使用

安装Anaconda 使用firefox打开Ananconda网址Anaconda | The Worlds Most Popular Data Science Platform 下载后有.sh文件&#xff1a; Anaconda3-2022.10-Linux-x86_64.sh 进入所在目录打开终端并输入 $ bash Anaconda3-2022.10-Linux-x86_64.sh 然后开始安装。 对于给…

SAP MM学习笔记1-SAP中扩张的概念,如何将一个物料从工厂A扩张到工厂B

MM中在创建物料的时候&#xff0c;最低也得创建如下5个view。 基本数据1 基本数据2 购买管理 会计1 会计2 1&#xff0c;扩张是什么 有时候&#xff0c;你想增加其他的View&#xff0c;比如保管场所 等&#xff0c;你不能用MM02来做编辑&#xff0c;要用MM01来做扩张。这就是扩…

OSPF的多区域特性 (电子科技大学TCP/IP实验三)

一&#xff0e;实验目的 1、掌握OSPF 协议中区域的类型、特征和作用 2、掌握OSPF 路由器的类型、特征和作用 3、掌握OSPF LSA 分组的类型、特征和作用 4、理解OSPF 区域类型、路由器类型和OSPF LSA 分组类型间的相互关系 二&#xff0e;预备知识 1、静态路由选择和动态路…

分享美容美发会员管理系统功能的特点_美容美发会员管理系统怎么做

人们越来越关心美发&#xff0c;美发行业发展迅速&#xff0c;小程序可以连接在线场景&#xff0c;许多美发院也开发了会员卡管理系统。那么一个实用的美发会员管理系统怎么制作呢&#xff1f;它有什么功能&#xff1f;我们一起来看看~&#xff08;干货满满&#xff0c;耐心看完…

Lenovo Legion Y530-15ICH电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。硬件型号驱动情况主板Lenovo Legion Y530-15ICH处理器Intel Core™ i7-8750H (Coffee-Lake)已驱动内存16GB RAM DDR4 2667MHz已驱动硬盘2TB HP EX950 PCI-E Gen3 x4 NVMe SSD已驱动显卡Intel UHD Graphics 630Nvidia GTX 10…

电子科技大学TCP/IP实验一——IP分组和ARP协议

目录 一&#xff0e;实验目的 二&#xff0e;预备知识 三&#xff0e;实验原理 四&#xff0e;实验内容 五&#xff0e;实验步骤 六、实验数据及结果分析 七、实验结论 八、总结及心得体会 九、对本实验过程及方法、手段的改进建议 一&#xff0e;实验目的 1、掌握 IP…

Lambda表达式的本质

一直想写一篇文章&#xff0c;来总结lambda表达式&#xff0c;但是之前感觉总结的不是特别到位&#xff0c;现在看了几篇文章和视频后&#xff0c;感觉对lambda表达式有了比较深刻的认识&#xff0c;现在进行记录总结如下&#xff1a; lambda表达式又叫做匿名函数&#xff0c;…

数据恢复软件EasyRecovery Photo16新版本功能特点介绍

EasyRecovery Photo16是一款支持Mac/Wind平台进行恢复图片的专业工具&#xff0c;尤其是各种流行单反相机RAW格式文件&#xff0c;以及超大型视频文件等&#xff0c;摄影爱好者使用。EasyRecovery是一款非常专业的硬盘数据恢复工具&#xff0c;可以帮你恢复丢失的数据&#xff…

【论文极速读】VQ-VAE:一种稀疏表征学习方法

【论文极速读】VQ-VAE&#xff1a;一种稀疏表征学习方法 FesianXu 20221208 at Baidu Search Team 前言 最近有需求对特征进行稀疏编码&#xff0c;看到一篇论文VQ-VAE&#xff0c;简单进行笔记下。如有谬误请联系指出&#xff0c;本文遵循 CC 4.0 BY-SA 版权协议&#xff0c;…

华为OD机试题,用 Java 解【矩阵扩散】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

java简单学习

Java 基础语法 一个 Java 程序可以认为是一系列对象的集合&#xff0c;而这些对象通过调用彼此的方法来协同工作。下面简要介绍下类、对象、方法和实例变量的概念。 对象&#xff1a;对象是类的一个实例&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个对象&#xff…

01-Maven基础-简介安装、基本使用(命令)、IDEA配置、(写jar,刷新自动下载)、依赖管理

文章目录0、Maven1、Maven 简介2、Maven 安装配置安装配置步骤3、Maven 基本使用Maven 常用命令Maven 生命周期IDEA 配置 MavenMaven 坐标详解IDEA 创建 Maven 项目IDEA 导入 Maven 项目配置 Maven-Helper 插件 (非常实用的小插件)依赖管理使用坐标导入 jar 包依赖范围0、Maven…

任何人均可上手的数据库与API搭建平台

编写API可能对于很多后端开发人员来说&#xff0c;并不是什么难事儿&#xff0c;但如果您主要从事前端功能&#xff0c;那么可能还是有一些门槛。 那么有没有工具可以帮助我们降低编写API的学习门槛和复杂度呢&#xff1f; 今天就来给大家推荐一个不错的开源工具&#xff1a;…

初识C++模板

文章目录前言1.模板概念2.函数模板1.示例用法1. 注意事项2.函数模板的原理3.函数模板的实例化4.模板参数的匹配原则3.类模板4.总结前言 本文主要围c中的模板进行介绍。模板是c中一个比较重要的概念&#xff0c;由于模板的存在&#xff0c;c才能进行泛型编程。模板的存在大大增…

针孔成像模型零基础入门(三)

2020年爆火的Nerf&#xff08;神经辐射场&#xff09;横空出世&#xff0c;据说只要用手机拍照&#xff0c;然后喂给模型&#xff0c;就可以生成3D模型了&#xff0c;我试过了&#xff0c;确有此事&#xff01; 那我们有想过&#xff0c;为什么可以从二维的图片里面获取物体三…

【7】linux命令每日分享——cat查看文件内容

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

Linux网络配置(NAT)

在搭配好一台虚拟机的时候想要下载&#xff0c;安装些什么但一直失败这个时候就可以检查一下网络是否连接这里我们使用centos7举例子使用命令——ifconfig由此可见我们的系统中目前有3个网卡ens33——用于接入外网&#xff0c;该网卡默认关闭lo——用于访问本地网络&#xff0c…

[数据结构]:04-循环队列(数组)(C语言实现)

目录 前言 已完成内容 循环队列实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-QueueCommon.cpp 04-QueueFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言代码。使用C引用主要是为了…

1.7校验码:校验码、规则校验码-奇偶校验、检验码-循环校验码CRC、模2除法、校验码-海明校验

1.7校验码&#xff1a;校验码、规则校验码-奇偶校验、检验码-循环校验码CRC、模2除法、校验码-海明校验校验码校验码-奇偶校验编码规则检验码-循环校验码CRC编码规则什么是模2除法如何计算校验码校验码-海明校验校验码 计算机在接收相应信息的时候能够识别的的都是一些电器信号…

【Spring6】| Spring的入门程序、集成Log4j2日志框架

目录 一&#xff1a;Spring的入门程序 1. Spring的下载 2. Spring的jar文件 3. 第一个Spring程序 4. 第一个Spring程序详细剖析 5. Spring6启用Log4j2日志框架 一&#xff1a;Spring的入门程序 1. Spring的下载 官网地址&#xff1a;https://spring.io/ 官网地址&…