js 类、原型及class

 js   一直允许定义类。ES6新增了相关语法(包括class关键字)让创建类更容易。新语法创建的类和老式的类原理相同。js 的类和基于原型的继承机制与Java等语言中的类和继承机制有着本质区别。

1 类和原型

类意味着一组对象从同一个原型对象继承属性。因此,原型对象是类的核心特征。

用工厂函数创建和初始化该类的新实例:

function range(from, to) {let r = Object.create(range.methods);r.from = from;r.to = to;return r;
}range.methods = {includes(x) {return this.from <= x && x <= this.to;},*[Symbol.iterator]() {for (let x = Math.ceil(this.from); x <= this.to; x++)yield x;},toString() {return "(" + this.from + "..." + this.to + ")";},}let r = range(1,3);
console.log(r.includes(2));
console.log(r + ""); // 调用的是toString()方法
console.log(r); // 打印对象本身,而非调用toString()方法
console.log([...r])

2 类和构造函数

只有函数(不包括箭头函数、生成器函数和异步函数)对象才有prototype属性。

上面定义类的写法非习惯写法,因为它没有定义构造函数。构造函数要使用new关键字调用,会自动创建新对象,因此构造函数本身只需初始化新对象的状态。构造函数调用的关键在于构造函数的prototype属性将被用作新对象的原型。

function Range(from,to) {this.from = from;this.to = to;
}// 原型属性名必须命名为prototype
Range.prototype = {includes(x) {return this.from <= x && x <= this.to;},*[Symbol.iterator]() {for (let x = Math.ceil(this.from); x <= this.to; x++)yield x;},toString() {return "(" + this.from + "..." + this.to + ")";}
}let r = new Range(1,3);
console.log(r.includes(2));
console.log(r + "");
console.log(r)
console.log([...r])

2.1 instanceof

当且仅当两个对象继承同一个原型对象时,它们才是同一个类的实例。instanceof 操作符用于检查某个对象是否是某个特定类的实例。

严格来讲,instanceof操作符并非检查对象是否通过某个构造函数初始化,而是检查对象是否继承了原型。(不一定是直接继承)

let prototype = {}function Person() {}function Animal() {}let p = new Person();console.log( p instanceof Person); // true
console.log( p instanceof Animal); // falsePerson.prototype = prototype
Animal.prototype = prototypelet p2 = new Person()
console.log( p2 instanceof Person); // true
console.log( p2 instanceof Animal); // true

2.2 constructor 属性

prototype属性的值是一个对象,其有一个不可枚举的constructor属性,该属性的值就是prototype所属的函数对象:

let F = function() {};

let p = F.prototype;

let c = p.constructor;

c === F; //true

3 使用class关键字定义类

class关键字是在ES6才引入的。

使用class来定义类:

class Person {constructor(age) {this.age = age;}showAge() {console.log(this.age);}}let p = new Person(12);
p.showAge();let Animal = class {constructor(name) {this.name = name}showName() {console.log(this.name)}
}let a = new Animal("大象");
a.showName()

与函数声明不同,类声明不会“提升”(函数定义就像是会被提升到包含文件或包含函数顶部一样,而类声明不会)。

类声明除了语句到形式外,还有表达式的形式。不过这种形式并不常用:

let Persopn = class { constructor() {} }

3.1 静态方法

在class体中,把static关键字放在方法声明前面可以定义静态方法。静态方法是作为构造函数而非原型的属性定义的。

class Person {static hello() {console.log("hello word")}
}Person.hello(); // hello word
let p = new Person();
p.hello(); // 报错,p.hello is not a function

静态函数必须通过构造函数而非实例调用。

3.2 获取和设置方法

在class 体内,可像对象字面量中一样定义获取方法和设置方法,唯一的区别是类体内的方法后面不加逗号。

class Person {set age(val) {if (val <= 0) throw new TypeError("年龄不能小于0")this.age = val}
}let person = new Person();
person.age = -1
console.log(person.age)

4 子类

ES6之前定义子类的方式是通过原型,ES6则通过extends定义子类。

4.1 子类与原型

function Person() {console.log("Person的构造器")
}Person.prototype = {constructor: Person,showType() {console.log("Person")}
}function Man() {console.log("Man的构造器")
}Man.prototype = Object.create(Person.prototype)
let man = new Man();
man.showType()
console.log(man.constructor)Man.prototype.constructor = Man
console.log(man.constructor)

只有在知道父类实现细节的前提下才可能这样定义子类,健壮的子类化机制应该允许类调用父类的方法和构造函数,在ES6之前,js中没有简单的方法做到这些。

4.2 通过extends和super创建子类

class Person {constructor() {console.log("Person:" + new.target)}
}class Man extends Person {constructor() {super();console.log(this)console.log("Man")}
}class Woman extends Person {constructor() {super();console.log("Woman")}
}let man = new Man();
let woman = new Woman()

注意事项:

1)使用extends关键字定义了一个类,则该类的构造函数必须使用super()调用父类构造器。
    2)在通过super()调用父类构造器之前,不能在构造器中使用this关键字。
    3)new.target引用的是被调用的构造函数。

在实际开发中,并不建议创建很多子类,建议通过“组合”的方式来替代继承。

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

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

相关文章

跨专业申请成功|金融公司经理赴美国密苏里大学访学交流

J经理所学专业与从事工作不符&#xff0c;尽管如此&#xff0c;我们还是为其成功申请到美国密苏里大学经济学专业的访问学者职位&#xff0c;全家顺利过签出国。 J经理背景&#xff1a; 申请类型&#xff1a; 自费访问学者 工作背景&#xff1a; 某金融公司经理 教育背景&am…

(视频教程)单细胞转录组多组差异基因分析及可视化函数

很久以前&#xff0c;我们发布过一个单细胞多组差异基因可视化的方法。跟着Cell学单细胞转录组分析(八):单细胞转录组差异基因分析及多组结果可视化。主要复现参考的是这篇发表在《Cell》上的文章。可以将多个组的差异结果展示出来。 &#xff08;reference&#xff1a;A Spati…

XPath:学习使用XPath语法提取HTML/XML文档中的数据使用语法

以下是一些XPath语法示例&#xff0c;用于提取HTML/XML文档中的数据&#xff1a; 选择元素&#xff1a; 选择所有p元素&#xff1a; //p 选择根元素&#xff1a; / 属性匹配&#xff1a; 选择class属性为"example"的div元素&#xff1a; //div[classexample] 文本内容…

在VScode中执行npm、yarn命令报错解

在VScode中执行npm、yarn命令报错解 我使用的是vnm安装好npm&#xff0c;在WindowsR 界面是可以运行查看出版本的&#xff1b;但是在VScode中报错。 查了很多资料&#xff0c;我这种情况的原因是在VScode中默认使用的终端是Powershell&#xff0c;然后我切换到系统的cmd则可以…

原生微信小程序使用 wxs;微信小程序使用 vant-weapp组件

1.原生微信小程序使用 wxs 1.内嵌 WXS 脚本 2. 定义外链 wxs 3. 使用外连wxs 在这里插入图片描述 2. 微信小程序使用 vant weapp 1.安装步骤 2. 安装包管理(package.json)文件的方法 操作顺序 &#xff1a;文档地址 如果使用 typescript 需要操作步骤3&#xff0c;否则不…

python语言学习

序言 此系列用于总结python语言的相关知识点&#xff0c;用于帮助自己和有缘人查阅 1、python基本数据类型 python基本数据类型 – 字符串

使用 wxPython 和 pymupdf进行 PDF 加密

PDF 文件是一种常见的文档格式&#xff0c;但有时候我们希望对敏感信息进行保护&#xff0c;以防止未经授权的访问。在本文中&#xff0c;我们将使用 Python 和 wxPython 库创建一个简单的图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;用于对 PDF 文件进行加密…

自动化运维:Ansible基础与命令行模块操作

目录 一、理论 1. Ansible 2.部署Ansible自动化运维工具 3.Ansible常用模块 4.hostsinverntory主机清单 二、实验 1.部署Ansible自动化运维工具 2.ansible 命令行模块 3.hostsinverntory主机清单 三、问题 1. ansible远程shell失败 2.组变量查看webservers内主机ip报…

基于Java+SpringBoot+Vue前后端分离美食推荐商城设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

显著性检验(Significance Test)

参考链接&#xff1a;Click Here 显著性检验&#xff08;Significance Test&#xff09;主要分为两个类别&#xff1a; Statistical Significance Test (统计显著性检验) 计量方式&#xff1a;p-value < 0.05 目的&#xff1a;检验原始分布与目标分布之间是否具有显著差异性…

如何在树莓派上使用Nginx搭建本地站点并通过内网穿透实现远程访问

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 安装 Nginx&#xff08;发音为“engine-x”&#xff09;可以将您的树莓派变成一个强大的 Web 服务器&#xff0c;可以用于托管网站或 Web 应用程序。相比其他 Web 服务器&#xff0c;Ngi…

时间和日期--Python

1. 时间&#xff1a;time模块 总结&#xff1a;2. datetime模块 相比与time模块&#xff0c;datetime模块的接口更直观、更容易调用 2.1 datetime模块定义的类 &#xff08;1&#xff09;datetime.date:表示日期的类。常用的属性有&#xff1a;year、month、day; &#xff…

九大ES5特性,巩固你的JavaScript基础

文章目录 1. 变量声明和作用域&#xff1a;使用 var 关键字声明变量函数作用域和全局作用域变量提升 2. 数据类型&#xff1a;基本数据类型&#xff1a;Number、String、Boolean、null、undefined引用数据类型&#xff1a;Object、Array、Function、Date 3. 函数&#xff1a;函…

vue中form、table和input标签过长

form标签过长 效果&#xff1a; 代码&#xff1a; <el-form-item v-for"(item,index) in ticketEditTable1" :label"item.fieldNameCn" :propitem.fieldName :key"item.fieldNameCn" overflow"":rules"form[item.fieldName…

Linux 中的 sysctl 命令及示例

介绍 Linux管理员使用该命令在运行时sysctl读取或修改内核参数。无需重新启动即可实时控制和修改网络、 I/O 操作和内存管理设置的选项对于高可用性系统至关重要。 了解如何使用该sysctl命令及其选项来动态调整系统性能。

Android中使用JT808协议进行车载终端通信的实现和优化

JT808是一种在中国广泛应用的车载终端通信协议&#xff0c;用于车辆与监控中心之间的数据通信。下面是关于Android平台上使用JT808协议进行通信的一般步骤和注意事项&#xff1a; 协议了解&#xff1a;首先&#xff0c;您需要详细了解JT808协议的规范和定义。该协议包含了通信消…

【halcon深度学习】图像分割数据集格式的转换

前言 目前用于**图像分割的**数据集&#xff0c;我目前接触到的用的比较多的有&#xff1a; 1 PASCAL VOC 2 COCO 3 YOLO 4 Halcon自己的格式&#xff08;其实就是Halcon字典类型&#xff09;当前我涉及到计算机视觉中的数据集格式有&#xff0c;PASCAL VOC、COCO 和 YOLO 用于…

软件设计师学习笔记3-CPU组成

目录 1.计算机结构 1.1计算机的外设与主机 1.2计算机各部分之间的联系(了解一下即可) 2.CPU结构 1.计算机结构 1.1计算机的外设与主机 1.2计算机各部分之间的联系(了解一下即可) 该图片来自希赛软考 注&#xff1a;黄色的是传递数据的数据总线&#xff0c;白色的是传递控…

表和Json的相互操作

目录 一、表转Json 1.使用 for json path 2.如何返回单个Json 3.如何给返回的Json增加一个根节点呢 4.如何给返回的Json增加上一个节点 二、对Json基本操作 1.判断给的字符串是否是Json格式 2.从 JSON 字符串中提取标量值 3. 从 JSON 字符串中提取对象或数组 4. 更…

【Linux】进程概念,轻松入门【下篇】

目录 1. 基本概念 2. 常见环境变量 常见环境变量指令 &#xff08;1. PATH &#xff08;2. HOME &#xff08;3. SHELL 3.环境变量的组织形式 &#xff08;1&#xff09;通过代码如何获取环境变量 &#xff08;2&#xff09;普通变量与环境变量的区别 &#xff08;3&…