前端JavaScript篇之对象创建的方式有哪些?

目录

  • 对象创建的方式有哪些?
    • 1. 工厂模式:
    • 2. 构造函数模式:
    • 3. 原型模式:
    • 4. 混合模式:
    • 5. 动态原型模式:
    • 6. 寄生构造函数模式:
    • 7. 字面量方式:


对象创建的方式有哪些?

JavaScript中创建对象的方式有多种,其中常用的有工厂模式、构造函数模式、原型模式、混合模式、动态原型模式和寄生构造函数模式。

1. 工厂模式:

使用一个函数封装创建对象的细节,通过调用函数来创建对象。但是对象无法和某个类型联系起来,缺乏类型识别。

function createPerson(name, age) {let person = {} // 创建一个空对象person.name = name // 给对象添加属性person.age = ageperson.sayHello = function () {// 给对象添加方法console.log("Hello, I'm " + this.name + '!')}return person // 返回对象
}let person1 = createPerson('张三', 18) // 创建对象
let person2 = createPerson('李四', 20)person1.sayHello() // 调用对象的方法
person2.sayHello()

请添加图片描述

在这个例子中,我们定义了一个 createPerson 函数,它接受两个参数 nameage。在函数内部,我们创建了一个空对象 person,并给它添加了两个属性 nameage,以及一个方法 sayHello。最后,我们返回这个对象。通过调用 createPerson 函数,我们可以创建多个对象,每个对象都有自己的 nameagesayHello 方法。

工厂模式的优点在于可以很好地封装对象的创建过程,从而提高代码的可维护性和可读性。但是,工厂模式无法识别对象的类型,因此无法使用 instanceof 运算符来判断对象的类型。另外,如果要添加新的方法或属性,需要修改工厂函数的代码,这可能会导致代码的不稳定性。

2. 构造函数模式:

使用构造函数模式创建对象,定义一个函数,通过 new 关键字调用函数,将 this 指向新建的对象,从而达到复用的目的。这种方式可以识别对象的类型。

function Person(name, age) {this.name = namethis.age = agethis.sayHello = function () {console.log("Hello, I'm " + this.name + '!')}
}let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)person1.sayHello() // 调用对象的方法
person2.sayHello()

请添加图片描述

在这个例子中,我们定义了一个 Person 构造函数,它接受两个参数 nameage。在函数内部,我们使用 this 关键字给对象添加了两个属性 nameage,以及一个方法 sayHello。使用 new 关键字调用构造函数时,会创建一个新的对象,并将 this 关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person 构造函数,我们可以创建多个对象,每个对象都有自己的 nameagesayHello 方法。

构造函数模式的优点在于可以识别对象的类型,因此可以使用 instanceof 运算符来判断对象的类型。另外,如果要添加新的方法或属性,只需要在构造函数内部添加即可,这样更加灵活。但是,由于每个对象都会创建自己的方法,因此会占用更多的内存空间。

3. 原型模式:

使用原型对象来添加公用属性和方法,实现代码复用。每个函数都有一个 prototype 属性,使用原型模式创建对象,定义一个构造函数,将对象的属性和方法添加到构造函数的原型对象上。这种方式可以实现属性和方法的共享,从而节省内存空间。

function Person(name, age) {this.name = namethis.age = age
}Person.prototype.sayHello = function () {console.log("Hello, I'm " + this.name + '!')
}let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)person1.sayHello() // 调用对象的方法
person2.sayHello()

请添加图片描述

在这个例子中,我们定义了一个 Person 构造函数,它接受两个参数 nameage。在函数内部,我们使用 this 关键字给对象添加了两个属性 nameage。然后,我们将 sayHello 方法添加到构造函数的原型对象上。使用 new 关键字调用构造函数时,会创建一个新的对象,并将 this 关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person 构造函数,我们可以创建多个对象,每个对象都有自己的 nameage 属性,以及共享的 sayHello 方法。

原型模式的优点在于可以实现属性和方法的共享,从而节省内存空间。由于每个对象共享同一个原型对象上的方法,因此不会占用额外的内存空间。另外,如果要添加新的方法或属性,只需要在原型对象上添加即可,这样更加灵活。但是,由于所有对象共享同一个原型对象,因此如果一个对象修改了原型对象上的属性或方法,会影响到其他对象。

4. 混合模式:

组合使用构造函数模式和原型模式,通过构造函数来初始化对象的属性,通过原型对象来实现函数方法的复用。结合构造函数模式和原型模式的优点,既可以识别对象的类型,又可以实现属性和方法的共享。

function Person(name, age) {this.name = namethis.age = age
}Person.prototype.sayHello = function () {console.log("Hello, I'm " + this.name + '!')
}let person1 = new Person('张三', 18) // 创建对象
let person2 = new Person('李四', 20)person1.sayHello() // 调用对象的方法
person2.sayHello()function Student(name, age, grade) {Person.call(this, name, age) // 继承属性this.grade = grade
}Student.prototype = Object.create(Person.prototype) // 继承方法
Student.prototype.constructor = Student // 修复 constructorStudent.prototype.study = function () {console.log(this.name + ' is studying in grade ' + this.grade + '.')
}let student1 = new Student('王五', 16, 10) // 创建对象
let student2 = new Student('赵六', 17, 11)student1.sayHello() // 调用继承自 Person 的方法
student1.study() // 调用自己的方法
student2.sayHello()
student2.study()

请添加图片描述

在这个例子中,我们定义了一个 Person 构造函数,它接受两个参数 nameage。在函数内部,我们使用 this 关键字给对象添加了两个属性 nameage。然后,我们将 sayHello 方法添加到构造函数的原型对象上。使用 new 关键字调用构造函数时,会创建一个新的对象,并将 this 关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Person 构造函数,我们可以创建多个对象,每个对象都有自己的 nameage 属性,以及共享的 sayHello 方法。

接着,我们定义了一个 Student 构造函数,它继承自 Person 构造函数。使用 call 方法调用 Person 构造函数,将 this 关键字指向新建的 Student 对象,并传入 nameage 参数,从而继承了 Person 构造函数的属性。然后,我们将 Student 构造函数的原型对象指向一个新的 Person 构造函数的原型对象,从而继承了 Person 构造函数的方法。最后,我们添加了一个 study 方法,用于 Student 对象自己的行为。

使用 new 关键字调用 Student 构造函数时,会创建一个新的对象,并将 this 关键字指向这个新对象。最后,构造函数会返回这个新对象。通过调用 Student 构造函数,我们可以创建多个对象,每个对象都有自己的 nameagegrade 属性,以及继承自 Person 构造函数的 sayHello 方法和自己的 study 方法。

混合模式的优点在于既可以识别对象的类型,又可以实现属性和方法的共享。通过继承构造函数模式的属性和原型模式的方法,可以更加灵活地创建对象。但是,由于需要继承两个部分的内容,因此代码量较多。

5. 动态原型模式:

动态原型模式是一种设计模式,用于在JavaScript中创建对象。它的主要思路是在构造函数内部判断是否需要初始化原型,如果需要,则在构造函数内部定义原型方法。将原型方法赋值的创建过程移动到构造函数的内部,通过对属性是否存在的判断,实现仅在第一次调用函数时对原型对象赋值一次的效果。

function Person(name, age) {this.name = namethis.age = age// 判断是否需要初始化原型if (typeof this.sayHello !== 'function') {// 定义原型方法Person.prototype.sayHello = function () {console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')}}
}// 创建两个Person对象
var person1 = new Person('Alice', 25)
var person2 = new Person('Bob', 30)// 调用原型方法
person1.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.
person2.sayHello() // 输出: Hello, my name is Bob and I am 30 years old.

请添加图片描述

在上述代码中,我们定义了一个Person构造函数,它接受nameage作为参数,并将它们赋值给实例变量。然后,我们使用动态原型模式来检查是否需要初始化原型方法sayHello。如果原型中不存在sayHello方法,那么我们就在构造函数内部定义该方法。

这样做的好处是,每次创建新的Person对象时,不会重复地定义原型方法。只有在第一次创建对象时,才会初始化原型方法。这样可以节省内存,并且避免了每个实例都拥有相同的原型方法的副本。

通过使用动态原型模式,我们可以灵活地定义构造函数和原型方法,并确保它们在需要的时候被正确地初始化。

6. 寄生构造函数模式:

寄生构造函数模式是一种设计模式,它通过在一个普通的构造函数内部创建并返回一个新对象,从而实现对构造函数的扩展。这个新对象通常被称为"寄生对象"。

function Person(name, age) {var obj = {} // 创建一个空对象// 对空对象进行属性和方法的添加obj.name = nameobj.age = ageobj.sayHello = function () {console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')}return obj // 返回新创建的对象
}// 创建一个Person对象
var person = new Person('Alice', 25)// 调用对象的方法
person.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.

请添加图片描述

在上述代码中,我们定义了一个Person构造函数,它接受nameage作为参数。在构造函数内部,我们创建了一个空对象obj,并向其添加了nameage属性以及sayHello方法。

最后,我们将新创建的对象obj返回,作为构造函数的结果。这样,在调用new Person()时,会得到一个包含了指定属性和方法的新对象。

使用寄生构造函数模式可以在不改变原始构造函数的情况下,对其进行扩展。这种模式常用于需要在原始构造函数的基础上添加额外功能或修改返回对象的情况下。然而,需要注意的是,寄生构造函数模式会导致每个新对象都拥有自己的方法副本,可能会造成内存浪费。因此,在使用该模式时要谨慎考虑其适用性和性能影响。

7. 字面量方式:

字面量方式是一种直接使用花括号{}来定义对象的方式。

// 创建一个对象并定义属性和方法
var person = {name: 'Alice',age: 25,sayHello: function () {console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.')}
}// 访问对象的属性和调用方法
console.log(person.name) // 输出: Alice
console.log(person.age) // 输出: 25
person.sayHello() // 输出: Hello, my name is Alice and I am 25 years old.![请添加图片描述](https://img-blog.csdnimg.cn/direct/89a64e636e56468bb8d122c13b5c64d7.png)

在上述代码中,我们使用字面量方式创建了一个名为person的对象。通过花括号{},我们直接在对象内部定义了属性nameage,以及方法sayHello

然后,我们可以通过点号.来访问对象的属性,例如person.nameperson.age。同时,我们也可以使用person.sayHello()来调用对象的方法。

字面量方式创建对象简单明了,适合创建单个对象或者只需要临时使用的对象。它不需要使用构造函数或原型,并且可以直接在对象内部定义属性和方法,非常方便。然而,由于每次创建对象都需要重新定义属性和方法,所以不适合创建大量相似的对象,这种情况下可以考虑使用其他方式,如构造函数或工厂模式。

总结:JavaScript中创建对象的方式有多种,每种方式都有其特点和适用场景,根据实际情况选择合适的方式来创建对象。工厂模式、构造函数模式、原型模式、混合模式、动态原型模式和寄生构造函数模式都是常用的创建对象的方式。在选择创建对象的方式时,需要注意代码的可读性、可维护性和性能等方面。

持续学习总结记录中,回顾一下上面的内容:
对象创建的方式有很多种。比较常见的包括工厂模式(像工厂一样创建对象)、构造函数模式(使用函数初始化对象)、原型模式(通过原型克隆对象)、混合模式(结合多种方式创建对象)、动态原型模式(在运行时扩展对象功能)、寄生构造函数模式(在构造函数内部创建对象并返回)、字面量方式(直接使用{}创建对象)。这些方式各有特点,可以根据具体需求选择最适合的方式来创建对象。

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

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

相关文章

春晚魔术和约瑟夫问题

春晚的魔术实际上是一个约瑟夫问题,最终的结果是魔术开始时确定的几个变量确定好的,扑克牌只是道具和障眼法。网上一查这个问题发现颇有历史渊源,17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个…

房屋租赁系统的Java实战开发之旅

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

WebSocket 通信流程,注解和Spring实现WebSocket ,实战多人聊天室系统

一、前言 实现即时通信常见的有四种方式-分别是:轮询、长轮询(comet)、长连接(SSE)、WebSocket。 ①短轮询 很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由客户端浏览器对服务…

机器学习2--逻辑回归(案列)

糖尿病数据线性回归预测 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_diabetes diabetesload_diabetes() datadiabetes[data] targetdiabetes[target] feature_namesdiabetes[feature_names] data.shape df …

2024刘谦春晚第二个扑克牌魔术

前言 就是刚才看春晚感觉这个很神奇,虽然第一个咱模仿不过来,第二个全国人民这么多人,包括全场观众都有成功,这肯定是不需要什么技术,那我觉得这个肯定就是数学了,于是我就胡乱分析一通。 正文 首先准备…

Mysql Day04

mysql体系结构 连接层服务层引擎层(索引)存储层 存储引擎 存储引擎是基于表建立的,默认是innoDB show create table tb; 查看当前数据库支持的存储引擎 show engines; InnoDB 特点 DML(数据增删改)遵循ACID模…

MongoDB的分片集群(二) :mongodb4.x分片集群离线搭建开启安全认证

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 相关文章: MongoDB的分片集群(一) : 基础知识 在《MongoDB的分片集群(一) : 基础知识》中梳理了分片集群的基础知识…

opencv计算机视觉

树莓派主机的无键盘解决 进入控制面板,更改适配器设置,WIFI属性,勾选 1.将网线两头分别接入树莓派和笔记本的网线接口 2.在无线连接属性那里勾选允许其他用户连接 3.运行cmd使用arp -a查看树莓派ip地址,或者使用ipscanner查看 cmd…

JavaIO读取C101.txt文件

一、split分割带空格的字符串(四种方法及其区别) 参考:https://blog.csdn.net/yezonghui/article/details/106455940 String str "a b c d";String[] arr1 str.split(" "); //仅分割一个空格 String[] arr2 str…

c++之说_11|自定义类型 enum(枚举)与enumclass (c11新枚举)

至于枚举 会用就行 至少目前我感觉没什么太多问题 enum 被称为无作用域枚举 , enumclass / enumstruct 被称为有作用域枚举 看到了吧 语法规则 和 struct 差不多 只不过枚举成员 只是一个标志 它本质是数值 从上到下 下面的数根据上面的数 加 1 也可以直接…

前端JavaScript篇之对闭包的理解

目录 对闭包的理解用途循环中使用闭包解决 var 定义函数的问题 对闭包的理解 闭包是指一个函数能够访问并操作其词法作用域(定义时所在的作用域)之外的变量的能力。它可以通过在一个函数内部创建另一个函数来实现。内部函数可以访问外部函数的局部变量、…

【维生素C语言】附录:strlen 函数详解

写在前面:本篇将专门为 strlen 函数进行讲解,总结了模拟实现 strlen 函数的三种方法,并对其进行详细的解析。手写库函数是较为常见的面试题,希望通过本篇博客能够加深大家对 strlen 的理解。 0x00 strlen函数介绍 【百度百科】str…

Cobalt Strike 的使用及拓展

Cobalt Strike是一款以Metasploit为基础的GUI框架式渗透测试工具,集成了端 口转发、服务扫描、 自动化溢出、多模式端口监听、exe 、PowerShell木马生成 等,主要用于团队作战,能让多个渗透者同时连接到团体服务器上,共享渗透资 源…

Leetcode2560. 打家劫舍 IV

Every day a Leetcode 题目来源:2560. 打家劫舍 IV 解法1:二分答案 动态规划 给定数组 nums,从中选择一个长度至少为 k 的子序列 A,要求 A 中没有任何元素在 nums 中是相邻的。 最小化 max⁡(A)。 看到「最大化最小值」或者…

基于vue+node.js的校园跳蚤市场系统多商家

校园跳蚤市场系统可以在短时间内完成大量的数据处理、帮助用户快速的查找校园跳蚤市场相关信息,实现的效益更加直观。校园跳蚤市场系统中采用nodejs技术和mysql数据库。主要包括管理员、发布者和用户三大部分,主要功能是实现对个人中心、用户管理、发布者…

数据分析基础之《pandas(7)—高级处理2》

四、合并 如果数据由多张表组成,那么有时候需要将不同的内容合并在一起分析 1、先回忆下numpy中如何合并 水平拼接 np.hstack() 竖直拼接 np.vstack() 两个都能实现 np.concatenate((a, b), axis) 2、pd.concat([data1, data2], axis1) 按照行或者列…

【Opencv学习】04-图像加法

文章目录 前言一、图像加法混合1.1 代码1.2 运行结果 二、图像的按位运算-组合相加2.1 代码2.2 运行结果示例:PPT平滑切换运行结果 总结 前言 简单说就是介绍了两张图如何组合在一起。 1、混合,透明度和颜色会发生改变 2、组合,叠加起来。可…

大厂的供应链域数据中台设计

关注我,紧跟本系列专栏文章,咱们下篇再续! 作者简介:魔都技术专家兼架构,多家大厂后端一线研发经验,各大技术社区头部专家博主,编程严选网创始人。具有丰富的引领团队经验,深厚业务架…

2/10 BFS初探

其实在我看来解决全排列问题&#xff0c;核心还是顺序&#xff0c;想清楚结束条件&#xff0c;然后输出&#xff0c;以n3为例 #include<iostream> using namespace std; const int N 10; int path[N];//保存序列 int state[N];//数字是否被用过 int n; void dfs(int u) …

FPGA_工程_基于rom的vga显示

一 框图 二 代码修改 module Display #(parameter H_DISP 1280,parameter V_DISP 1024,parameter H_lcd 12d150,parameter V_lcd 12d150,parameter LCD_SIZE 15d10_000 ) ( input wire clk, input wire rst_n, input wire [11:0] lcd_xpos, //lcd horizontal coo…