JavaScript - js进阶 -创建对象的几种方式 - 工厂模式

本文探讨了创建对象的三种主要方式:字面量、工厂函数和构造函数,分别介绍了它们的优缺点及应用场景,如字面量的简洁但不适合大量重复创建,工厂函数利于复用但失去血缘关系,而构造函数则能方便区分对象且有血缘关系,但存在属性值为方法的内存问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建对象的几种方式

字面量

  • 简单粗暴
  • 不适合创建多个同样类型的对象的场景
const obj ={ name:"悟空",height:100,age:5000};

工厂函数

  1. 容易理解

  2. 失去血缘关系,无法简单分辨对象的特征

    在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>创建对象的几种方式</title>
    </head>
    <body></body>
    <script>
        // 1. 字面量(语法糖) {}
        let obj1 = { name: "张三", age: 29 };

        // 优点: 简单直观

        // 2. new Object(): 标准语法  构造函数
        let obj2 = new Object({ name: "李四", age: 28 });

        // 优点: 区分明确(暂时看不出来)
        console.log(obj1, obj2);

        // 3. 工厂模式(设置模式: Dessign Model)

        // 需求: 创建50个学生对象
        // let stu1 = { name: '值1', age: 0 }
        // let stu1 = { name: '值1', age: 0 }
        // ...

        // 特点: 结构一样, 数据不同

        // 想办法: 复用结构 --> 函数复用代码, 数据灵活: 参数
        function studentFactory(name, age) {
            return {
                name: name,
                age: age,
            };
        }

        let stu1 = studentFactory("张三", 29);
        let stu2 = studentFactory("李四", 28);

        console.log(stu1, stu2);

        // 以上所有方式产生的对象: 都是Object对象: 无法区分
        // 有办法进行对象的分类: new Array() 得到一个数组
        console.log(new Array());
    </script>
</html>

构造函数

  1. 可以方便的创建对象
  2. 拥有血缘关系
  3. 还有后续更多的优势
    // 1 声明函数 
    function createStudent(name, age) {
      // 2 通过 this 赋值
      this.name = name;
      this.age = age;
    }

    // 3 通过 new 来创建对象
    const obj = new createStudent("悟能", 83);

    console.log(obj);
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>自定义构造函数</title>
    </head>
    <body></body>
    <script>
        // 构造函数: 本质是函数, 构造函数的 作用: 创建对象

        /*
        构造函数的语法要求

        1. 定义构造函数
        * 为了区分普通函数: 构造函数的名字: 大驼峰 (普通函数小驼峰)
        * 构造函数内部: 直接使用 this.属性名 = 属性值 增加属性
        * 构造函数不需要return: 自动返回 对象 (跟调用方式有关)

        2. 调用构造函数
        * new 构造函数名字()
    */

        // 自定义构造函数: 学生
        function Student(name, age) {
            // this直接产生属性
            this.name = name;
            this.age = age;

            // 不需要return: 自动返回值
        }

        // 调用构造函数: new Student()
        const s1 = new Student("周巧", 18);
        console.log(s1);

        function Teacher(name, age) {
            this.name = name;
            this.age = age;
        }

        const t1 = new Teacher("柏松", 29);
        console.log(t1);

        // 总结
        // 自定义构造函数的目的: 实现数据的分类(区别对待)
        // 构造函数是由开发者规定的: 使用应该用构造函数的用法
    </script>
</html>

构造函数的弊端

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>构造函数-属性值为方法的弊端</title>
    </head>
    <body></body>
    <script>
        // 对象内部属性的值: 不限定数据类型

        function Student(name, age) {
            this.name = name;
            this.age = age;

            // 学生具有学习能力(方法)
            this.study = function () {
                // 输出: 谁在学习
                console.log(this.name + "正在学习");
            };
        }

        const s1 = new Student("周w", 29);
        const s2 = new Student("周q", 18);

        // 访问属性
        console.log(s1, s2);
        console.log(s1.name, s1.age);

        // 访问方法
        s1.study();
        s2.study();

        console.log(s1.study == s2.study); // false

        // 说明s1.study和s2.study是两个不同的内存地址: 其实事情一样(本质只要一块内存)

        // 解决方案: 想办法让不同对象里面的study函数, 指向同一块内存地址
        // 函数是一种复合数据类型: 函数的变量传值是引用传递

        // 将study函数变成一个全局函数: 属性指向全局函数
        function Teacher(name, age) {
            this.name = name;
            this.age = age;

            this.study = study;
        }

        function study() {
            console.log(this.name + "正在学习");
        }

        const t1 = new Teacher("三儿", 29);
        const t2 = new Teacher("四儿", 25);
        console.log(t1, t2);

        t1.study();
        t2.study();

        console.log(t1.study === t2.study); // true: 内存地址一样

        // 上述方案: 解决了 内存重复占用的问题(只有一份)

        // 缺点: 内存是由一个全局变量 study保存的: 容易被污染
        study = 1;

        console.log(s1.study, s2.study); // 已经存在的对象: 不受影响

        const t3 = new Teacher("张三", 40);
        console.log(t3.study); // 1 : 不再指向函数
    </script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Henry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值