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,我们相信,如果我们关注用户…

oracle创建用户和赋权

在 Oracle 数据库中,要创建一个用户并授予权限,可以按照以下步骤进行操作:步骤一:创建用户 sql CREATE USER yonghuming IDENTIFIED BY 123456; 这里将 yonghuming 替换为要创建的用户名,123456 替换为用户的密码。步…

Retrofit源码阅读

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

控制台厂商配额查询

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

java default注解怎么设置数组默认值

在Java中,为注解的数组类型属性设置默认值时,需要使用大括号{}包围数组元素。如果数组默认值只有一个元素,也可以直接使用该元素而不需要大括号。下面是一个示例,展示了如何为注解的数组类型属性设置默认值: import j…

Spark on k8s 源码解析执行流程

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

Activity top resumed state loss timeout for ActivityRecord 报错原因是?

Activity top resumed state loss timeout for ActivityRecord 这个错误通常不是直接显示给用户看的,而是Android系统内部日志(如Logcat)中的一个错误信息,它指示了系统在尝试恢复或管理某个Activity的状态时遇到了问题。这个错误…

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

文章目录 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&…

Python 类与对象:深入理解与应用

在 Python 中,类是一种抽象数据类型,用于描述具有相同属性和方法的对象集合。类通过属性(变量)和方法(函数)来定义对象的行为。对象是类的实例化结果,它可以具备类定义的所有特性。Python 中的类…

ROS2 RQT

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

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

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

【云原生】Kubernetes----ETCD数据的备份与恢复

目录 引言 一、ETCD数据备份 (一)确定备份策略 (二)使用etcdctl工具进行备份 1.安装etcdctl命令 2.设置ETCDCTL_API环境变量 (三)执行备份 二、数据还原 (一)创建新资源 &…

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

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

广州自闭症机构哪家好

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

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

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

SAP_ABAP相关日语单词

基本概念 1. プログラミング言語 (プログラミングげんご, Puroguramingu gengo) - 编程语言 2. 開発 (かいはつ, Kaihatsu) - 开发 3. システム (システム, Shisutemu) - 系统 4. モジュール (モジュール, Mojūru) - 模块 5. トランザクションコード (トランザクションコード,…

探索旅游卡项目的八大黄金赛道,你离月入十几万仅一步之遥!

作为旅游卡项目的推广精英,我深知在这个充满机遇与挑战的时代,选择正确的赛道至关重要。今天,我将从定位、内容、产品、流量、变现这五个核心维度出发,为你揭秘旅游卡项目的八大热门方向。如果你正对旅游充满热情,或拥…

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

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

【leetcode--最小栈】

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…