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

JS中批量创建对象的三种模式(小白笔记)

创建对象需要改进的地方:使用Object构造函数或者对象字面量可以方便地创建对象,但这些方式也有明显的不足: 创建具有同样属性的多个对象, 需要重复编写很多代码.

1. 工厂模式

工厂模式是一种常见的设计模式,广泛应用于软件工程领域,用于抽象创建特定对象的过程.

按照特定接口 创建对象的模式:

// 编写特定的接口
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 = creatPerson('nico',29,'lawyer');
let person2 = creatPerson('yue',29,'coder');

使用工厂模式 可以解决创建多个类似对象的问题, 但是这些新创建的对象是什么类型? 没有对应的标识!

2. 构造函数模式

ECMAScript中的构造函数 是用于创建特定类型的对象. 原生构造函数Object和Arrary等,运行时可以直接在执行环境中使用.

也可以自定义构造函数, 以函数的形式为自己的对象类型定义属性和方法.

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(..)
let person2 = new person(...)

按照惯例, 构造函数名称的首字母要大写,非构造函数首字母小写.

要创建构造函数Person的实例对象 ,需要使用new操作符.

使用new操作符 调用构造函数 会支持以下操作

    ① 在内存中创建一个新对象

    ② 新对象内部的 [[ Prototype ]] 特性 被赋值为 构造函数的prototype属性.

    ③ 构造函数内部的this指向新对象

    ④ 执行构造函数内部的代码,为新对象添加属性

    ⑤ 如果构造函数返回非空对象,则返回该对象. 否则返回刚创建的新对象.

    在上面的例子中, person1和person2分别保存着Person的不同实例。这两个对象都有一个construction 属性指向 Person .      construction: 建筑物 构造 结构

console.log( person1.construction == Person);  //true
console.log( person2.construction == Person ); //true

construction 本来是用于标识对象类型的, 但是有更可靠好用的 instanceof 操作符来确定对象类型

console.log( person1 instanceof Person) //true  person1是Person构造函数的实例
console.log( person1 instanceof Object) //true  Person1也是Object构造函数的实例 
                                       // 因为所有的自定义对象都继承自 Object 
console.log( person2 instanceof Person) //true
console.log( person2 instanceof Object) //true

相比于 工厂模式 , 自定义构造函数 有一个很大的好处, 就是可以确保实例被 标识为特定的类型. 比如上面的person1和person2 都被标识为 Person类型

关于构造函数的说明 :

  ①. 构造函数可以写成函数声明的形式 即 function Person(){...} ,也可以写成函数表达式的形式 即let Person = function (){...};

  ②. 使用构造函数实例化时 ,如果不想传参数,构造函数后面的括号可以不加,

即 let person1 = new Person;

  ③. 构造函数也是函数,函数也可以是构造函数.

构造函数和普通函数的唯一区别 就是调用方式不同. 任何函数只要使用new 操作符调用 就是构造函数,而不使用new操作符调用的函数就是普通函数.

// 使用new操作符 --构造函数
let person1 = new Person('nico',29,'lawyer');
person1.sayName(); //nico

// 作为普通函数调用 --全局作用域中this指向windows(在浏览器中)
Person("grep",30,"coder");
this.sayName(); //grep

// 在另一个对象中调用
let o = new Object();
    //通过call调用 并将对象o指定为作用域 Person内部的this指向对象O
Person.call(o, 'kris',20,'actor'); 
o.sayName(); //kris

   ④. 构造函数可以改进的地方

构造函数的主要问题: 构造函数内部定义的方法,会在每个实例上都创建一遍. 比如上面的 person1和person2 内部都有sayName函数. JS中函数是对象,所以在实例中定义sayName函数时,都会初始化一个新的Function实例对象. 因为sayName函数都是做一样的事情,所以没有必要在两个Person实例中分别定义两个Function实例.

这个问题可以通过使用 原型模式 来解决.

3. 原型模式

每个函数都会创建一个prototype属性 ,这个属性是一个对象,包含 应该由特定引用类型的实例共享的属性和方法. (如Person.prototype)实际上 这个对象就是通过 调用构造函数创建的对象的原型.(如 person1.__proto__)

console.log(Person.prototype === person1.__proto__); //true

使用原型对象的好处 就是,在它上面定义的属性和方法 可以被对象实例共享.

原来在构造函数中直接赋值给对象实例的值 ,可以直接赋值给该构造函数的原型.

function Person(){}
Person.prototype.name = "Nicols";
Person.prototype.age = 19;
Person.prototype.job = "lawyer";
Person.prototype.sayName = function (){
  console.log(this.name);
};
let person1 = new Person;
person1.sayName() //Nicols
let person2 = new Person;
person2.sayName() //Nicols

上面代码中, 所有属性和sayName()方法 都直接添加到了构造函数Person的prototype属性上. 构造函数体中 什么也没有. 调用该构造函数 创建的新对象仍然拥有相应的属性和方法.

和构造函数模式不同, 使用原型模式定义的属性和方法 是由所有的实例共享的.

因此 person1和person2 访问的是同一个属性和同一个sayName函数. 这样就解决了在实例对象中重复创建多个function函数对象的问题.

--------本文主要内容来自《JS高级程序设计》-------------------------


http://www.kler.cn/a/463537.html

相关文章:

  • UniApp | 从入门到精通:开启全平台开发的大门
  • 分析服务器 systemctl 启动gozero项目报错的解决方案
  • Alist-Sync-Web 网盘自动同步,网盘备份相互备份
  • STLG_01_05_程序设计C语言 - 数据类型概念解析
  • 异步爬虫之aiohttp的使用
  • 【AI日记】25.01.02 kaggle 比赛 3-1
  • 使用MFC编写一个paddleclas预测软件
  • 嵌入式系统 第七讲 ARM-Linux内核
  • CSS系列(48)-- Custom Highlight API详解
  • 如何实现分片上传功能:基于 Vue 和 iView 上传组件的详细教程
  • 如何寻找到文件在电脑中安装的位置
  • C++ 变量:深入理解与应用
  • 端口被占用
  • 【ArcGIS微课1000例】0136:制作千层饼(DEM、影像、等高线、山体阴影图层)
  • UML类图示例-CPP
  • C# OpenCV机器视觉:目标跟踪
  • 【数据结构】(Python)差分数组。差分数组与树状数组结合
  • vs2022编译opencv 4.10.0
  • Spring Boot项目启动时显示MySQL连接数已满的错误
  • 1Panel自建RustDesk服务器方案实现Windows远程macOS
  • 2021.12.28基于UDP同信的相关流程
  • Python-Pdf转Markdown
  • sudo mkdir -p /etc/docker其中的 -p 什么意思?
  • ubuntu 如何使用vrf
  • PyTorch快速入门教程【小土堆】之torchvision中的数据集使用
  • 1月第四讲:Java Web学生自习管理系统