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

news2024/10/6 1:43:22

目录

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


对象创建的方式有哪些?

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

1. 工厂模式:

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

function createPerson(name, age) {
  let person = {} // 创建一个空对象
  person.name = name // 给对象添加属性
  person.age = age
  person.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 = name
  this.age = age
  this.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 = name
  this.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 = name
  this.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 // 修复 constructor

Student.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 = name
  this.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 = name
  obj.age = age
  obj.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://www.coloradmin.cn/o/1444122.html

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

相关文章

RUST入门:如何用vscode调试rust程序

RUST已经流行一阵子了,但是比较系统的IDE介绍还是比较少,这里我简单介绍 一下如何用vscode实现单步调试rust程序,就像我们平时调试c程序一样。 学习资料网站 首先,介绍几个学习rust的好网站, Rust程序设计语言Rust语…

vue.js基于springboot的实验室设备管理系统10345

(1)设备信息模块:记录设备的基本信息,如设备采购来源信息、设备需求量、当前数量、日期等。 (2) 用户模块:教师职工。实现对用户个人信息、消息管理和实验室设备的查询使用申请等。 (3) 管理员模块:实现对所有设备信息的增删改查&…

论文笔记:相似感知的多模态假新闻检测

整理了RecSys2020 Progressive Layered Extraction : A Novel Multi-Task Learning Model for Personalized Recommendations)论文的阅读笔记 背景模型实验 论文地址:SAFE 背景 在此之前,对利用新闻文章中文本信息和视觉信息之间的关系(相似…

迅为RK3588开发板ubuntu和window互传图形界面直接拖拽进行文件传输

确保以及安装了 VMware Tools。如下图所示表示已安装过了。 和 windows 端文件夹间传输一样直接拖拽进去即可,如下图所示: 也可拖拽到终端,如下图所示: 更多内容可以B站搜索迅为RK3588开发板

不安全的 HTTP请求 漏洞原理以及修复方法

漏洞名称:不安全的HTTP方法、危险的HTTP方法 漏洞描述:不安全的HTTP方法一般包括:TRACE、PUT、DELETE、COPY 等。其中最常见的为TRACE方法可以回显服务器收到的请求,主要用于测试或诊断,恶意攻击者可以利用该方法进行…

【Linux】学习-基础IO—下

Linux基础IO—上 重定向 通过上篇的学习,我们了解了文件描述符的分配规则是遍历指针数组,用没有被使用的最小下标作为新的文件描述符,也就是我们可以通过关闭三个标准流文件并使用他们原先所占用的0,1,2描述符。 那…

2024 年 6 款最佳 PDF 编辑器,您可以免费获得

PDF 作为与 Windows、iOS、Linux 和各种其他操作系统兼容的安全文档格式而享有盛誉。这种广泛的兼容性使 PDF 成为一种流行的选择,几乎每个用户都会在不同的环境中遇到 PDF 文件。无论是合同、发票、电子书、信用卡对账单、银行对账单、税务表格还是保险文件&#x…

【芯片设计- RTL 数字逻辑设计入门 番外篇 9 -- SOC 中PL端与PS端详细介绍】

文章目录 Programmable Logic and Processing SystemPL(Programmable Logic)特点PS和PL之间的协同设计和开发工具 Programmable Logic and Processing System 在系统级芯片(SoC)的上下文中,“PL” 通常指的是可编程逻…

第二节 zookeeper基础应用与实战

目录 1. Zookeeper命令操作 1.1 Zookeeper 数据模型 1.2 Zookeeper服务端常用命令 1.3 Zookeeper客户端常用命令 1.3.1 基本CRUD 1.3.2 创建临时&顺序节点 2. Zookeeper JavaAPI操作 2.1 Curator介绍 2.2 引入Curator 2.3 建立连接 2.4 添加节点 2.5 修改节点 …

Blazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端管理组件

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…

导数的定义【高数笔记】

【含义】可以抽象成,在一个极其短的时间段内,温度差 / 时间差 【本质】瞬间的平均值 【分类】可以分成几类?每类需要注意的点 【导数存在的必要条件】 【导数与极限的关系】可以参考导数的定义的式子 【题型解法】分几个题型?每个…

【MySQL进阶之路】生产案例:每一个月左右MySQL就会出现性能抖动问题

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送! 在我后台回复 「资料」 可领取编程高频电子书! 在我后台回复「面试」可领取硬核面试笔记! 文章导读地址…

Linux第45步_通过搭建“DNS服务器”学习图形化配置工具

学习的意义:通过搭建“DNS服务器”,来学习“图形化配置工具”。“DNS服务器”,我们用不到,但为后期移植linux系统服务,因为在移植系统时,需要用到这个“图形化配置工具”。 1、“menuconfig图形化配置工具…

贾玲的腹肌,你也可以拥有

​​​​​​​ 贾玲的腹肌,你也可以拥有 大年初一,有学员来给顾问老师拜年,聊起了现在春节档热门电影,贾玲导演的第二部作品《热辣滚烫》,也聊起了她瘦身100斤后的模样。 学员:贾玲瘦了 100 斤&#xff0…

c语言中的隐式类型转换

数据类型转化 我们在实际编程中,不管你是有意的还是无意的,有时候都会让两个不同类型的数据参与运算,编译器为了能够生成CPU可以正常 执行的指令,往往会对数据做类型转换,将两个不同类型的数据转换成同一种数据类型。…

C++重新入门-循环

目录 1.循环类型 while循环: for循环 基于范围的for循环(C11) do...while 循环 2.循环控制语句 3.无限循环 有的时候,可能需要多次执行同一块代码。一般情况下,语句是顺序执行的:函数中的第一个语句先执行,接着…

寒假 day10

1、请使用递归实现n! #include<stdio.h> #include<string.h> #include<stdlib.h>int fun(int m) {if(m0)return 1;else{return m*fun(m-1);} } int main(int argc, const char *argv[]) {int m;printf("please enter m:");scanf("%d",…

视觉SLAM十四讲学习笔记(二)三维空间刚体

哔哩哔哩课程连接&#xff1a;视觉SLAM十四讲ch3_哔哩哔哩_bilibili​ 目录 一、旋转矩阵 1 点、向量、坐标系 2 坐标系间的欧氏变换 3 变换矩阵与齐次坐标 二、实践&#xff1a;Eigen&#xff08;1&#xff09; 运行报错记录与解决 三、旋转向量和欧拉角 1 旋转向量 …

OpenCV-35 查找轮廓

一、 什么是图像轮廓 图像轮廓是具有相同颜色或灰度的连续点的曲线&#xff0c;轮廓在形状分析和物体的检测识别中很有用。 用于图形分析物体的识别和检测 注意点&#xff1a; 为了检测的准确性&#xff0c;需要先对图像进行二值化或Canny操作。画轮廓时会修改输入的图像&a…

fast.ai 深度学习笔记(六)

深度学习 2&#xff1a;第 2 部分第 12 课 原文&#xff1a;medium.com/hiromi_suenaga/deep-learning-2-part-2-lesson-12-215dfbf04a94 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自 fast.ai 课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;…