JavaScript高级程序设计(第四版)--学习记录之对象、类和面向对象编程(中)

创建对象方式

工厂模式:用于抽象创建特定对象的过程。可以解决创建多个类似对象的问题,但没有解决对象标识问题。(即新创建的对象是什么类型)

function createPerson(name, age, job) { let o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { console.log(this.name); }; return o; 
} 
let person1 = createPerson("Nicholas", 29, "Software Engineer"); 
let person2 = createPerson("Greg", 27, "Doctor");

构造函数模式:用于创建特定类型对象。构造函数名称的首字母都是要大写的,用来区分非构造函数。

function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function() { console.log(this.name); }; 
} 
let person1 = new Person("Nicholas", 29, "Software Engineer"); 
let person2 = new Person("Greg", 27, "Doctor"); 
person1.sayName(); // Nicholas 
person2.sayName(); // Greg

原型模式:每个函数都会创建一个prototype属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。

function Person() {} 
Person.prototype.name = "Nicholas"; 
Person.prototype.age = 29; 
Person.prototype.job = "Software Engineer"; 
Person.prototype.sayName = function() { console.log(this.name); 
}; 
let person1 = new Person(); 
person1.sayName(); // "Nicholas" 
let person2 = new Person(); 
person2.sayName(); // "Nicholas" 
console.log(person1.sayName == person2.sayName); // true

继承的方式:接口继承和实现继承。接口继承在 ECMAScript 中是不可能的,因为函数没有签名。实现继承是 ECMAScript 唯一支持的继承方式,而这主要是通过原型链实现的。

原型链 

其基本思想就是通过原型继承多个引用类型的属性和方法。
function SuperType() { this.property = true; 
} 
SuperType.prototype.getSuperValue = function() { return this.property; 
}; 
function SubType() { this.subproperty = false; 
} 
// 继承 SuperType 
SubType.prototype = new SuperType(); 
SubType.prototype.getSubValue = function () {
return this.subproperty; 
}; 
let instance = new SubType(); 
console.log(instance.getSuperValue()); // true

原型链虽然是实现继承的强大工具,但它也有问题。问题一:出现在原型中包含引用值的时候。前面在谈到原型的问题时也提到过,原型中包含的引用值会在所有实例间共享,这也是为什么属性通常会在构造函数中定义而不会定义在原型上的原因。在使用原型实现继承时,原型实际上变成了另一个类型的实例。这意味着原先的实例属性摇身一变成为了原型属性。
问题二:子类型在实例化时不能给父类型的构造函数传参。
function SuperType() { this.colors = ["red", "blue", "green"]; 
} 
function SubType() {} 
// 继承 SuperType 
SubType.prototype = new SuperType(); 
let instance1 = new SubType(); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
let instance2 = new SubType(); 
console.log(instance2.colors); // "red,blue,green,black"

解决原型包含引用值导致的继承问题

盗用构造函数:在子类构造函数中调用父类构造函数。优点可以在子类构造函数中向父类构造函数传参。缺点:必须在构造函数中定义方法,因此函数不能重用。

function SuperType(name){ this.name = name; 
} 
function SubType() { // 继承 SuperType 并传参SuperType.call(this, "Nicholas"); // 实例属性this.age = 29; 
} 
let instance = new SubType(); 
console.log(instance.name); // "Nicholas"; 
console.log(instance.age); // 29

 组合继承:综合了原型链和盗用构造函数,使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。

function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; 
} 
SuperType.prototype.sayName = function() { console.log(this.name); 
}; 
function SubType(name, age){ // 继承属性SuperType.call(this, name); this.age = age; 
} 
// 继承方法
SubType.prototype = new SuperType(); 
SubType.prototype.sayAge = function() { console.log(this.age); 
}; 
let instance1 = new SubType("Nicholas", 29); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
instance1.sayName(); // "Nicholas"; 
instance1.sayAge(); // 29 
let instance2 = new SubType("Greg", 27); 
console.log(instance2.colors); // "red,blue,green" 
instance2.sayName(); // "Greg"; 
instance2.sayAge(); // 27

原型式继承

ES5通过增加 Object.create()方法将原型式继承的概念规范化了,这个方法接收两个

参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。
原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合。
let person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] 
}; 
let anotherPerson = Object.create(person); 
anotherPerson.name = "Greg"; 
anotherPerson.friends.push("Rob"); 
let yetAnotherPerson = Object.create(person); 
yetAnotherPerson.name = "Linda"; 
yetAnotherPerson.friends.push("Barbie"); 
console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"

寄生式继承

function createAnother(original){ let clone = object(original); // 通过调用函数创建一个新对象clone.sayHi = function() { // 以某种方式增强这个对象console.log("hi"); }; return clone; // 返回这个对象
}

寄生式组合继承

function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; 
} 
SuperType.prototype.sayName = function() { console.log(this.name); 
}; 
function SubType(name, age){ SuperType.call(this, name); // 第二次调用 SuperType() this.age = age; 
} 
SubType.prototype = new SuperType(); // 第一次调用 SuperType() 
SubType.prototype.constructor = SubType; 
SubType.prototype.sayAge = function() { console.log(this.age); 
};

寄生式组合继承算是引用类型继承的最佳模式!

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

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

相关文章

Android:移动垃圾软件

讲解政策相关,最近升级AI扫荡系统和证书防高风险,回复按留言时间来排,请耐心等待 移动垃圾软件 官方政策公告行为透明、信息披露清晰保护用户数据不要损害移动体验软件准则反垃圾软件政策Google API 服务用户数据政策官方政策公告 ​ 在 Google,我们相信,如果我们关注用户…

Retrofit源码阅读

动态代理在 Android 中的应用:Retrofit 源码解析 在之前的文章 《Andriod 网络框架 OkHttp 源码解析》 中我们分析了 OkHttp 的源代码。现在我们就来分析一下 OkHttp 的兄弟框架 Retrofit。关于 Retrofit 的注解的使用,可以参考其官方文档:h…

控制台厂商配额查询

概述 厂商推送限制 每个厂商通道都有对应的厂商配额和 QPS 限制,当请求超过限制且已配置厂商回执时,MobPush会采取以下措施: 当开发者推送请求超过厂商配额时,MobPush将通过自有通道进行消息下发。当开发者推送请求超过厂商 QPS…

Spark on k8s 源码解析执行流程

Spark on k8s 源码解析执行流程 1.通过spark-submit脚本提交spark程序 在spark-submit脚本里面执行了SparkSubmit类的main方法 2.运行SparkSubmit类的main方法,解析spark参数,调用submit方法 3.在submit方法里调用doRunMain方法,最终调用r…

算法-位图与底层运算逻辑

文章目录 1. 位图的理论基础2. 完整版位图实现3. 底层的运算逻辑-位运算 1. 位图的理论基础 首先我们要理解什么是位图, 位图的一些作用是什么 位图法就是bitmap的缩写。所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又…

Python+Pytest+Allure+Yaml+Pymysql+Jenkins+GitLab接口自动化测试框架详解

PythonPytestAllureYaml接口自动化测试框架详解 编撰人:CesareCheung 更新时间:2024.06.20 一、技术栈 PythonPytestAllureYamlJenkinsGitLab 版本要求:Python3.7.0,Pytest7.4.4,Allure2.18.1,PyYaml6.0 二、环境配置 安装python3.7&…

ROS2 RQT

1. RQT是什么 RQT是一个GUI框架,通过插件的方式实现了各种各样的界面工具。 强行解读下:RQT就像插座,任何电器只要符合插座的型号就可以插上去工作。 2.选择插件 这里我们可以选择现有的几个RQT插件来试一试,可以看到和话题、参…

金蝶云星空字段之间连续触发值更新

文章目录 金蝶云星空字段之间连续触发值更新场景说明具体需求:解决方案 金蝶云星空字段之间连续触发值更新 场景说明 字段A配置了字段B的计算公式,字段B配置了自动C的计算公式,修改A的时候,触发了B的重算,但是C触发不…

XMind2TestCase:高效测试用例设计工具

XMind2TestCase:高效测试用例设计工具 引言传统测试用例设计的问题1. Excel表格的局限性2. 传统测试管理工具的不足3. 自研测试管理工具的挑战 思维导图在测试用例设计中的应用思维导图的优势思维导图的挑战 简介安装使用方式命令行调用使用Web界面 使用示例XMind文…

广州自闭症机构哪家好

在广州,众多的自闭症康复机构中,星贝育园自闭症儿童康复学校以其独特的优势脱颖而出。 一、专业的师资团队 我们拥有一支经验丰富、专业素养极高的师资队伍。每位老师都经过严格的专业培训,深入了解自闭症儿童的特点和需求。他们不仅…

苍穹外卖项目 常用注解 + 动态sql

常用注解 常见的注解解析方法有两种: 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。运行期通过反射处理&…

【基于R语言群体遗传学】-3-计算等位基因频率

书接上文,我们讲完了哈代温伯格基因型频率,也使用数据进行了拟合,那么接下来就是考虑一些计算的问题: 【基于R语言群体遗传学】-1-哈代温伯格基因型比例-CSDN博客 【基于R语言群体遗传学】-2-模拟基因型(simulating …

WebKey备受瞩目的Web3.0新叙事,硬件与加密生态完美融合特性成为数字世界的新入口

在当今迅速发展的科技领域,Web3.0正在引领一场颠覆性的变革。而作为这一变革的先锋,WebKey无疑是备受瞩目的创新项目。它不仅代表了一种全新的技术趋势,更是数字世界中硬件与加密生态完美融合的典范。 硬件与加密生态的完美融合 WebKey的核心…

【QT】输入类控件

目录 Line Edit 核心属性 核心信号 正则表达式 示例:使用正则表达式验证输入框内容 示例:切换输入框密码模式下的显示状态 Text Edit 核心属性 核心信号 示例:获取多行输入框的内容同步显示到label 示例:获取文本的选…

一文讲懂npm link

前言 在本地开发npm模块的时候,我们可以使用npm link命令,将npm 模块链接到对应的运行项目中去,方便地对模块进行调试和测试 用法 包链接是一个两步过程: 1.为依赖项创建全局软链npm link。一个符号链接,简称软链&a…

二刷力扣——DP算法(子序列问题)

300. 最长递增子序列 定义是以本元素结尾&#xff0c;所以公式初始化都好弄。但是太慢 class Solution {public int lengthOfLIS(int[] nums) {int nnums.length;int[] dp new int[n];//以自己结尾的最长递增子序列dp[0]1;int maxzi1;for(int i1;i<n;i){dp[i]1;for(int j…

QT中QDomDocument读写XML文件

一、XML文件 <?xml version"1.0" encoding"UTF-8"?> <Begin><Type name"zhangsan"><sex>boy</sex><school>Chengdu</school><age>18</age><special>handsome</special>&l…

【YOLOv5进阶】——引入注意力机制-以SE为例

声明&#xff1a;笔记是做项目时根据B站博主视频学习时自己编写&#xff0c;请勿随意转载&#xff01; 一、站在巨人的肩膀上 SE模块即Squeeze-and-Excitation 模块&#xff0c;这是一种常用于卷积神经网络中的注意力机制&#xff01;&#xff01; 借鉴代码的代码链接如下&a…

在C#中使用RabbitMQ做个简单的发送邮件小项目 _

前言 好久没有做项目了&#xff0c;这次做一个发送邮件的小项目。发邮件是一个比较耗时的操作&#xff0c;之前在我的个人博客里面回复评论和友链申请是会通过发送邮件来通知对方的&#xff0c;不过当时只是简单的进行了异步操作。那么这次来使用RabbitMQ去统一发送邮件&#x…

vue中路由来回切换页面直接卡死

今天发现一个很严重的问题&#xff0c;项目好不容易做好了&#xff0c;结果页面多了&#xff0c;切换之后卡死。页面所有的交互效果都失效了。 排查了许久的错误原因最后发现原来是路由名称重复了。 如上图当页面跳转到riskdetails详细页面之后&#xff0c;框架则被这个详情页…