当前位置: 首页 > news >正文

对象创建的4种模式

1. 工厂模式

这种模式抽象了创建具体对象的过程,用函数来封装以特定接口创建对象的细节

缺点:没有解决对象识别的问题(即怎样知道一个对象的类型)

function createPerson(name, age, job) {var o = new Object();o.name = name;o.age = age;o.job = job;o.sayName = function() {alert(this.name)};return o;
}
const personOne = createPerson('lee', 29, 'Software Engineer')
const personTwo = createPerson('Gred', 24, 'Doctor')

2. 构造函数模式

 (1)与工厂模式相比构造函数模式

  • 没有显示地创建对象
  • 直接将属性和方法赋值给了this对象
  • 没有return语句
  • 区别于非构造函数,构造函数以大写字母开头

(2)要创建Person的新实例,必须使用new操作符

         以这种方式调用构造函数实际上会经历以下4个步骤:

  1. 创建一个新对象
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
  3. 执行构造函数的代码(为这个新对象添加属性) 
  4. 返回新对象
function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.sayName = function() {alert(this.name)};
}
const personOne = new Person('lee', 29, 'Software Engineer')
const personTwo = new Person('Gred', 24, 'Doctor')

(3)personOne和personTwo分别保存着Person的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person

console.log(personOne.constructor == Person) // true
console.log(personTwo.constructor == Person) // true

(4)以上例子中创建的所有对象既是Object的实例,同时也是Person的实例,这一点通过instanceof操作符可以得到验证。

console.log(personOne instanceof Person) // true
console.log(personOne instanceof Object) // true
console.log(personTwo instanceof Person) // true
console.log(personTwo instanceof Object) // true

(5)构造函数毕竟也是函数,不存在定义构造函数的特殊语法。任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。

// 当作构造函数使用
const person = new Person('lee', 29, 'Software Engineer');
person.sayName(); // 'lee'// 作为普通函数调用
Person('Gred', 24, 'Doctor') // 添加到window
window.sayName(); // 'Gred'// 在另外一个对象的作用域中调用
const o = new Object();
Person.call(o, 'Alice', 27, 'Nurse');
o.sayName(); // 'Alice'

缺点:每个方法都要在每个实例上重新创建一遍。

解决方法:把函数转移到构造函数外。

function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.sayName = sayName
}
function sayName() {alert(this.name)};
const personOne = new Person('lee', 29, 'Software Engineer')
const personTwo = new Person('Gred', 24, 'Doctor')

如上,两个实例的sayName共享了一个全局的sayName方法。解决了2个函数做同一件事的问题。但是新问题又来了

在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实
如果对象需要定义很多方法,那么就要定义很多全局函数,导致我们这个自定义的引用类型丝毫没有封装性可言。

3. 原型模式

(1) 针对以上构造函数的痛点,原型模式可以解决这些问题。

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的作用是包含可以由特定类型的所有实例共享的属性和方法。prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处就是不用在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。

function Person() {}
Person.prototype.name = 'lee';
Person.prototype.age = 29;
Person.prototype.job = 'Software Engineer';
Person.prototype.sayName = function() {alert(this.name)
};
const personOne = new Person();
personOne.sayName(); // 'lee'
const personTwo = new Person();
personTwo.sayName(); // 'lee'
console.log(personOne.sayName == personTwo.sayName); // true//简写
function Person(){}
Person.prototype = {constructor: Person,name: 'lee',age: 29,job: 'Software Engineer',sayName: function(){alert(this.name)}
};

(2)默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性这个属性是一个指向prototype属性所在函数的指针。如上例子,Person.prototype.constructor指向Person。

Person.prototype.constructor === Person // true

(3)当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。这个内部属性[ [ Prototype ] ],虽然无法访问到。但是可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。如果[ [ Prototype ] ]指向调用isPrototypeOf()方法的对象(Person.prototype),那么这个方法就返回true。

console.log(Person.prototype.isPrototypeOf(personOne)); // true
console.log(Person.prototype.isPrototypeOf(personTwo)); // true

(4)Object.getPrototypeOf() 这个方法返回[ [ Prototype ] ]的值

console.log(Object.getPrototypeOf(personOne) == Person.prototype); // true
console.log(Object.getPrototypeOf(personOne).name); // 'lee'
console.log(Object.getPrototypeOf(personTwo) == Person.prototype); // true
console.log(Object.getPrototypeOf(personTwo).name); // 'lee'

(5)使用delete可以删除实例中的属性

personOne.name = 'Alice';
console.log(personOne.name) // 'Alice'  来自实例
console.log(personTwo.name) // 'lee'  来自原型 
delete personOne.name;
console.log(personOne.name) // 'lee'  来自原型 

(6)hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中。如果该属性存在于实例中,则返回true。

personOne.name = 'Alice';
console.log(personOne.hasOwnProperty('name')) // true
console.log(personTwo.hasOwnProperty('name')) // false

(7)in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

personOne.name = 'Alice';
console.log('name' in personOne) // true name在实例中
console.log('name' in personTwo) // true name在原型中

(8)getOwnPropertyNames()方法得到所有实例属性,无论它是否可枚举。

const keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys); // ['constructor','name','age','job','sayName']

(9)可以随时给原型添加属性和方法,但是如果是重写整个原型对象,就相当于把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。

function Person(){}
const friend = new Person();
Person.prototype = {name: 'lee',age: 29,job: 'Software Engineer',sayName: function(){alert(this.name)}
};
friend.sayName(); // error
//因为这时的friend指向的是以前的Person,而以前的是没有sayName方法的,所以报错。
//而且这里旧的原型对象和新的原型对象的指针都指向Person

缺点:

(1)所有实例在默认情况下都将取得相同的属性值。(上面例子中定义的name,age等)(2)原型中存在引用类型,会导致每一个实例共享这个引用类型。如下例子:每一个实例中的friends会因为其中一个实例的修改,都共享了这个修改后的结果。

function Person(){}
Person.prototype = {constructor: Person,name: 'lee',age: 29,friends: ['Jack', 'Bob'],job: 'Software Engineer',sayName: function(){alert(this.name)}
};
const personOne = new Person();
const personTwo = new Person();
personOne.friends.push('Ivan');
console.log(personOne.friends); // ['Jack', 'Bob', 'Ivan']
console.log(personTwo.friends); // ['Jack', 'Bob', 'Ivan']
console.log(personOne.friends === personTwo.friends); // true

4. 组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。

function Person(name, age, job) {this.name = name;this.age = age;this.job = job;this.friends = ['Jack', 'Bob'];
}
Person.prototype = {constructor: Person,sayName: function() {alert(this.name);}}
const personOne = new Person('lee', 29, 'Software Engineer')
const personTwo = new Person('Gred', 24, 'Doctor')
personOne.friends.push('Van');
console.log(personOne.friends); // ['Jack', 'Bob', 'Ivan']
console.log(personTwo.friends); // ['Jack', 'Bob']
console.log(personOne.friends === personTwo.friends); // false
console.log(personOne.sayName === personTwo.sayName); // true

相关文章:

对象创建的4种模式

1. 工厂模式 这种模式抽象了创建具体对象的过程,用函数来封装以特定接口创建对象的细节 缺点:没有解决对象识别的问题(即怎样知道一个对象的类型) function createPerson(name, age, job) {var o new Object();o.name name;o.ag…...

如何判断 是否 需要 CSS 中的媒体查询

以下是一些常见的使用媒体查询的场景: 响应式布局:当设备的屏幕尺寸变化时,我们可以使用媒体查询来调整布局,以适应不同的屏幕尺寸。 设备特性适配:我们可以使用媒体查询来检测设备的特性,如设备方向、分辨…...

设计模式-装饰器模式(结构型)

装饰器模式 装饰器模式是一种结构模式,通过装饰器模式可以在不改变原有类结构的情况下向一个新对象添加新功能,是现有类的包装。 图解 角色 抽象组件:定义组件的抽象方法具体组件:实现组件的抽象方法抽象装饰器:实现…...

升级HarmonyOS 4.2,开启健康生活篇章

夏日来临,华为智能手表携 HarmonyOS 4.2 版本邀您体验,它不仅可以作为时尚单品搭配夏日绚丽服饰,还能充当你的健康管家,从而更了解自己的身体,开启智能健康生活篇章。 高血糖风险评估优化,健康监测更精准 …...

给gRPC增加负载均衡功能

在现代的分布式系统中,负载均衡是确保服务高可用性和性能的关键技术之一。而gRPC作为一种高性能的RPC框架,自然也支持负载均衡功能。本文将探讨如何为gRPC服务增加负载均衡功能,从而提高系统的性能和可扩展性。 什么是负载均衡? …...

【优选算法】详解target类求和问题(附总结)

目录 1.两数求和 题目: 算法思路: 代码: 2.!!!三数之和 题目 算法思路: 代码: 3.四数字和 题目: 算法思路: 代码: 总结&易错点&…...

【数据结构】图论入门

引入 数据的逻辑结构: 集合:数据元素间除“同属于一个集合”外,无其他关系线性结构:一个对一个,例如:线性表、栈、队列树形结构:一个对多个,例如:树图形结构&#xff1…...

11_1 Linux NFS服务与触发挂载autofs

11_1 Linux NFS服务与触发挂载服务 文章目录 11_1 Linux NFS服务与触发挂载服务[toc]1. NFS服务基础1.1 示例 2. 触发挂载autofs2.1 触发挂载基础2.2 触发挂载进阶autofs与NFS 文件共享服务:scp、FTP、web(httpd)、NFS 1. NFS服务基础 Netwo…...

开发uniapp 小程序时遇到的问题

1、【微信开发者工具报错】routeDone with a webviewId XXX that is not the current page 解决方案: 在app.json 中添加 “lazyCodeLoading”: “requiredComponents” uniapp的话加到manifest.json下的mp-weixin 外部链接文章:解决方案文章1 解决方案文章2 &qu…...

怎样快速获取Vmware VCP 证书,线上考试,voucher报名优惠

之前考一个VCP证书,要花大一万的费用,可贵了,考试费不贵,贵就贵在培训费,要拿到证书,必须交培训费,即使vmware你玩的很溜,不需要再培训了,但是一笔贵到肉疼的培训费你得拿…...

LeetCode 1141, 134, 142

目录 1141. 查询近30天活跃用户数题目链接表要求知识点思路代码 134. 加油站题目链接标签普通版思路代码 简化版思路代码 142. 环形链表 II题目链接标签思路代码 1141. 查询近30天活跃用户数 题目链接 1141. 查询近30天活跃用户数 表 表Activity的字段为user_id&#xff0c…...

华为FPGA工程师面试题

FPGA工程师面试会涉及多个方面,包括基础知识、项目经验、编程能力、硬件调试和分析等。以下是一些必问的面试题: 基础知识题: 请解释FPGA的基本组成和工作原理。描述FPGA中的可编程互联资源以及它们在构建复杂数字电路中的作用。请解释嵌入式多用途块(如BRAM、DSP slices、…...

Windows11上安装docker(WSL2后端)和使用docker安装MySQL和达梦数据库

Windows11上安装docker(WSL2后端)和使用docker安装MySQL和达梦数据库 1. 操作系统环境2. 首先安装wsl2.1 关于wsl2.2 安装wsl2.3 查看可用的wsl2.4 安装ubuntu-22.042.5 查看、启动ubuntu-22.04应用2.6 上面安装开了daili2.7 wsl的更多参考 3. 下载Docke…...

UnityXR Interactable Toolkit如何实现Climb爬梯子

前言 在VR中,通常会有一些交互需要我们做爬梯子,爬墙的操作,之前用VRTK3时,里面是还有这个Demo的,最近看XRI,发现也除了一个爬的示例,今天我们就来讲解一下 如何在Unity中使用XR Interaction Toolkit实现爬行(Climb)操作 环境配置 步骤 1:设置XR环境 确保你的Uni…...

sqli-labs 靶场 less-11~14 第十一关、第十二关、第十三关、第十四关详解:联合注入、错误注入

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 11 SQLI DUMB SERIES-11判断注入点 尝试在用户名这个字段实施注入,且试出SQL语句闭合方式为单…...

国内外网络安全现状分析

一、国内网络安全现状 1.1 国内网络安全威胁 国内的网络安全威胁主要表现在以下几个方面: 恶意软件:包括计算机病毒、蠕虫、木马和间谍软件等,它们能感染计算机系统、窃取敏感信息或破坏系统功能。网络钓鱼:通过伪装成可信任的…...

vscode copilot git commit 生成效果太差,用其他模型替换

问题 众所周知,copilot git commit 就像在随机生成 git commit 这种较为复杂的内容还是交给大模型做比较合适 方法 刚好,gitlens 最近开发了 AI commit的功能,其提供配置url api可以实现自定义模型 gitlens 只有3种模型可用&#xff1a…...

计算机毕业设计hadoop+spark+hive舆情分析系统 微博数据分析可视化大屏 微博情感分析 微博爬虫 微博大数据 微博推荐系统 微博预测系统

本 科 毕 业 论 文 论文题目:基于Hadoop的热点舆情数据分析与可视化 姓名: 金泓羽 学号: 20200804050115 导师: 关英 职称&…...

【MySQL】(基础篇二) —— MySQL初始用

MySQL初始用 目录 MySQL初始用基本语法约定选择数据库查看数据库和表其它的SHOW 在Navicat中,大部分数据库管理相关的操作都可以通过图形界面完成,这个很简单,大家可以自行探索。虽然Navicat等图形化数据库管理工具为操作和管理数据库提供了非…...

计算机网络 期末复习(谢希仁版本)第4章

路由器:查找转发表,转发分组。 IP网的意义:当互联网上的主机进行通信时,就好像在一个网络上通信一样,看不见互连的各具体的网络异构细节。如果在这种覆盖全球的 IP 网的上层使用 TCP 协议,那么就…...

如何使用Pandas处理数据?

一、技术难点 Pandas是Python中一个强大的数据处理和分析库,它提供了高效、灵活且易于使用的数据结构,主要用于数据清洗、转换、聚合和可视化等任务。然而,在使用Pandas处理数据时,也会遇到一些技术难点。 数据导入与导出&#…...

Error: spawn xdg-open ENOENT

报错:The CJS build of Vite’s Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details. VITE v5.1.4 ready in 2298 ms ➜ Local: http://localhost:80/ ➜ Network: http://10.0.4.13:80/ ➜…...

写给大数据开发,如何去掌握数据分析

这篇文章源于自己一个大数据开发,天天要做分析的事情,发现数据分析实在高大上很多,写代码和做汇报可真比不了。。。。 文章目录 1. 引言2. 数据分析的重要性2.1 技能对比2.2 业务理解的差距 3. 提升数据分析能力的方向4. 数据分析的系统过程4…...

大数据湖一体化运营管理建设方案(49页PPT)

方案介绍: 本大数据湖一体化运营管理建设方案通过构建统一存储、高效处理、智能分析和安全管控的大数据湖平台,实现了企业数据的集中管理、快速处理和智能分析。该方案具有可扩展性、高性能、智能化、安全性和易用性等特点,能够为企业数字化…...

大模型训练的艺术:从预训练到增强学习的四阶段之旅

文章目录 大模型训练的艺术:从预训练到增强学习的四阶段之旅1. 预训练阶段(Pretraining)2. 监督微调阶段(Supervised Finetuning, SFT)3. 奖励模型训练阶段(Reward Modeling)4. 增强学习微调阶段…...

Linux 网络设置

Linux 网络设置 查看及测试网络查看网络配置测试网络连接 设置网络地址参数使用网络配置命令修改网络配置文件 查看及测试网络 查看及测试网络配置是管理 Linux 网络服务的第一步,本节将学习 Linux 操作系统中的网络查看及测试命令。其中讲解的大多数命令以普通用户权限就可以…...

交易中的群体行为特征和决策模型

本文基于人的行为和心理特征,归纳出交易中群体的行为决策模型,并基于这个模型,分析股价波浪运行背后的逻辑,以及投机情绪的周期变化规律,以此指导交易,分析潜在的风险和机会,寻找并等待高性价比…...

Android14之向build.prop添加属性(二百一十九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP…...

Cargo

Cargo cargo是rust的构建系统和包管理工具,在安装rust的时候就一并安装了cargo。 > cargo --version cargo 1.78.0 (54d8815d0 2024-03-26)使用cargo创建项目 cargo new hello_cargo会生成 src 源码目录Cargo.tomlCargo.lock.gitignore 仓库文件 Cargo.toml…...

大学生如何学习node.js?

1. 学习 JavaScript 基础知识 语法:变量、数据类型、操作符、控制结构(if、switch、loops)。函数:定义、调用、参数、作用域。对象和原型:对象字面量、构造函数、继承。数组:方法(map、filter、…...

网站编辑怎么做/免费网站建设模板

【IT168 资讯】华为的三款模块化机架服务器产品已经将旧版Xeons更新到Skylake,从而提供更新的网络和存储选项。今年早些时候,华为开始对其服务器产品进行Skylake更新,从其E系列刀片服务器开始,即CH121和CH242 V5。现在已经转移到模…...

成交型网站制作/seo软件排行榜前十名

使用ping命令时经常会遇到这两种情况,就表示网络出了问题: 无法访问目标主机的原因 可以看到“无法访问目标主机”是来自一个IP的回复,实际上那个IP是一个路由器。因此“无法访问目标主机”实际上数据是发出去并且收到回复的,只…...

怎么做快播电影网站/百度推广登录平台怎么收费

1、前言我们经常涉及到数字与字符串之间的转换,例如将32位无符号整数的ip地址转换为点分十进制的ip地址字符串,或者反过来,总结一下。C语言提供了一些列的格式化输入输出函数,最基本的是面向控制台标准输出和输入的printf和scanf&…...

成都营销网站建设/如何做好网站站内优化

1.整型符号:int用处:用于计算和比较python3:全部都是整型python2:整型,长整型long123--十进制 转二进制方法:十进制数除2,取余数从下往上排;print(bin(十进制数))10101--二进制 转十进制方法&am…...

wordpress站点维护/网络推广是做什么工作的

线程池threadpool介绍 (Introduction) 随着芯片制造商致力于通过增加时钟速度来增加处理器内核,开发人员需要利用现代CPU的功能。 我们做到这一点的方法之一是在软件中实现并行算法。 One recent task I needed to perform at home was to find and document large …...

科技有限公司可以做网站建设吗/短视频营销案例

要实现的效果&#xff1a; 1、父节点选中&#xff0c;则以下的子节点全选中 2、父节点不选中。则以下的子节点全不选中 3、子节点仅仅要选中了一个&#xff0c;则父节点选中 4、子节点全不选中。则父亲节点不选中 <% page language"java" import"java.util.*…...